Skip to content

Commit 472075d

Browse files
authored
[DIT-3689] Explicit support for list and map variables, misc cleanup (#28)
* chore: .env > .gitignore * chore: update to latest version of Ditto CLI, `structured` format * chore: add deprecation notices for API related to `full` format * refactor: rm useless function * add examples for new variable types, rm deprecated examples * checkpoint; * feat: better support specific variable types * specific README additions for map and list variables * always fallback to rendering provided input * version bump * small updates from PR feedback
1 parent 289cc24 commit 472075d

File tree

14 files changed

+842
-1226
lines changed

14 files changed

+842
-1226
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
node_modules
33
build
44
dist
5+
.env

README.md

Lines changed: 89 additions & 118 deletions
Original file line numberDiff line numberDiff line change
@@ -94,46 +94,100 @@ const App = () => {
9494
Text items containing Ditto Variables default to rendering those variables as the variable name inside of a template tag:
9595

9696
```jsx
97-
<Ditto textId={textId} />;
98-
output = "The cart contains {{itemName}}.";
97+
<Ditto componentId="shopping-cart" />;
98+
output === "The cart contains {{itemName}}.";
9999
```
100100

101101
Template tags are automatically interpolated if a value for a given variable (keyed by the variable's name) is provided via the `variables` prop:
102102

103103
```jsx
104-
<Ditto textId={textId} variables={{ itemName: "apples" }} />
105-
output = "The cart contains apples."
104+
<Ditto componentId="shopping-cart" variables={{ itemName: "apples" }} />
105+
output === "The cart contains apples."
106106

107-
<Ditto textId={textId} variables={{ itemName: "pears" }} />
108-
output = "The cart contains pears."
107+
<Ditto componentId="shopping-cart" variables={{ itemName: "pears" }} />
108+
output === "The cart contains pears."
109109
```
110110

111111
If no value is provided for a variable, but that variable has a fallback value configured in the source data synced from Ditto (`structured` json format only), the fallback will be used:
112112

113113
```jsx
114-
// if the variable `itemName` had "some fruit" configured as a fallback in Ditto
115-
<Ditto textId={textId} variables={{}} />;
116-
output = "The cart contains some fruit.";
117-
```
118-
119-
```js
120-
// ✔️ source contains variable information, interpolation will occur
121-
{
114+
const source = {
122115
"shopping-cart": {
123116
"text": "The cart contains {{itemName}}.",
124117
"variables": {
125118
"itemName": {
126119
"example": "pears",
127-
"fallback": "some stuff",
120+
// ✔️ variable source data has a fallback value
121+
"fallback": "some fruit",
122+
"__type": "string"
128123
}
129124
}
130125
}
131126
}
132127

133-
// ✕ source doesn't contain variable information, interpolation won't occur
134-
{
135-
"shopping-cart": "The cart contains {{itemName}}."
128+
...
129+
130+
// ✔️ fallback value is used when variable value is not specified
131+
<Ditto componentId="shopping-cart" />;
132+
output === "The cart contains some fruit.";
133+
```
134+
135+
When passing data for a `list` variable, an error is logged to the console if the passed data doesn't correspond to a value in the list.
136+
137+
```js
138+
const source = {
139+
"shopping-cart": {
140+
"text": "The cart contains {{itemName}}.",
141+
"variables": {
142+
"itemName": [
143+
"apples",
144+
"pears",
145+
"oranges"
146+
]
147+
}
148+
}
149+
}
150+
151+
...
152+
153+
// ✔ value in list, no error logged
154+
<Ditto componentId="shopping-cart" variables={{ itemName: "pears" }} />
155+
output === "The cart contains pears."
156+
157+
// ❌ value NOT in list, error logged (but output retained)
158+
<Ditto componentId="shopping-cart" variables={{ itemName: "grapes" }} />
159+
output === "The cart contains pears."
160+
```
161+
162+
When passing data for a `map` variable:
163+
164+
- if the data corresponds to a map key, the corresponding value in the map is interpolated
165+
- if the data doesn't correspond to a map key, an error is logged to the console and the data is interpolated directly
166+
167+
```js
168+
const source = {
169+
"user-role": {
170+
"text": "You are {{role}} in this workspace.",
171+
"variables": {
172+
"role": {
173+
"admin": "an administrator",
174+
"editor": "an editor",
175+
"commenter": "a commenter",
176+
"__type": "map"
177+
}
178+
}
179+
}
136180
}
181+
182+
...
183+
184+
// ✔ in list, corresponding value interpolated
185+
<Ditto componentId="user-role" variables={{ role: "admin" }} />
186+
output === "You are an administrator in this workspace."
187+
188+
// ❌ NOT in list, error logged, passed data directly interpolated
189+
<Ditto componentId="user-role" variables={{ role: "owner" }} />
190+
output === "You are owner in this workspace."
137191
```
138192

139193
## Pluralization
@@ -144,28 +198,28 @@ When a text item has plural forms, the default plural form will be used when tha
144198

145199
```jsx
146200
<Ditto textId={textId} />;
147-
output = "The cart contains some items.";
201+
output === "The cart contains some items.";
148202
```
149203

150204
When a `count` prop is provided, the plural form to render (of those that are configured in Ditto) will be inferred based off of that value:
151205

152206
```jsx
153207
<Ditto textId={textId} count={3}/>
154-
output = "The cart contains a few items."
208+
output === "The cart contains a few items."
155209

156210
<Ditto textId={textId} count={10}/>
157-
output = "The cart contains many items."
211+
output === "The cart contains many items."
158212

159213
<Ditto textId={textId} count={0}/>
160-
output = "The cart contains nothing."
214+
output === "The cart contains nothing."
161215
```
162216

163217
Plurals can also be used in combination with [variables](#variable-interpolation):
164218

165219
```jsx
166220
// If the "many" plural form is "The cart contains many {{adjective}} items."
167221
<Ditto textId={textId} variables={{ adjective: "fun" }} count={10} />;
168-
output = "The cart contains many fun items.";
222+
output === "The cart contains many fun items.";
169223
```
170224

171225
The `count` prop is indexed to the following plural keys:
@@ -240,15 +294,15 @@ Which method you use depends on how you've configured your CLI options. Please r
240294

241295
#### Project
242296

243-
| Prop | Type | Description | Example |
244-
| ----------- | ---------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
245-
| `projectId` | string (semi-required) | ID of a project in Ditto; required if a `projectId` isn't found in an ancestor `DittoProvider` |
246-
| `textId` | string (optional) | ID of a single text item in Ditto | |
247-
| `frameId` | string (optional) | ID of a frame in Ditto | |
248-
| `blockId` | string (optional) | ID of a block in Ditto | |
249-
| `filters` | object (optional) | object of filters for text items returned. Currently supports a single parameter: tags, an array of tag strings | { tags: ["SELECTS"]} |
250-
| `variables` | object (optional) | A map of variable key-value pairs to interpolate in your text. | { email: "[email protected]" } |
251-
| `count` | number (optional) | This value is used to specify which plural case you wish to use | 1 |
297+
| Prop | Type | Description | Example |
298+
| ----------- | --------------------------------- | --------------------------------------------------------------------------------------------------------------- | ----------------------------------- |
299+
| `projectId` | string (semi-required) | ID of a project in Ditto; required if a `projectId` isn't found in an ancestor `DittoProvider` |
300+
| `textId` | string (optional) | ID of a single text item in Ditto | |
301+
| `frameId` | string (optional, **deprecated**) | ID of a frame in Ditto | |
302+
| `blockId` | string (optional, **deprecated**) | ID of a block in Ditto | |
303+
| `filters` | object (optional) | object of filters for text items returned. Currently supports a single parameter: tags, an array of tag strings | { tags: ["SELECTS"]} |
304+
| `variables` | object (optional) | A map of variable key-value pairs to interpolate in your text. | { email: "[email protected]" } |
305+
| `count` | number (optional) | This value is used to specify which plural case you wish to use | 1 |
252306

253307
##### Examples
254308

@@ -261,7 +315,7 @@ If you pass `textId`, the specified text string will be rendered:
261315
/>
262316
```
263317

264-
If you pass `frameId` and/or `blockId`, the specified frame/block object will be passed to a child function:
318+
**(deprecated)** If you pass `frameId` and/or `blockId`, **the specified** frame/block object will be passed to a child function:
265319

266320
```jsx
267321
<Ditto
@@ -281,8 +335,8 @@ In addition to the `<Ditto />` component, individual exports of each specific co
281335

282336
```js
283337
import {
284-
DittoFrame,
285-
DittoBlock,
338+
DittoFrame, // deprecated
339+
DittoBlock, // deprecated
286340
DittoText,
287341
DittoComponent, // rendering components from your Ditto component library
288342
} from "ditto-react";
@@ -316,89 +370,6 @@ const textPluralized = useDittoSingleText({
316370
});
317371
```
318372

319-
## Additional Examples
320-
321-
### Example: Single Text
322-
323-
The `Ditto` component can be used to fetch a specific text item from the Ditto project using its API ID. Note that you can edit IDs for text, blocks, and frames directly the Ditto web app:
324-
325-
```jsx
326-
<Ditto textId="text_601cc35c5bsdfe42cc3f6f8ac59" />
327-
```
328-
329-
### Example: Fetch Block
330-
331-
You can also fetch an entire Block in Ditto at once by specifying the `frameId` and the `blockId`.
332-
333-
It will return as an entire JSON object of the frame. You can pull out specific IDs of text you'd like to pass to its children.
334-
335-
```jsx
336-
<Ditto frameId="frame_601cc35d5be42cc3f6f8ad15" blockId="hero">
337-
{({ hero_h1, text_601cc35c5be42cc3f6f8ac46, hero_cta }) => (
338-
<div>
339-
<h1>{hero_h1}</h1>
340-
<h2>{text_601cc35c5be42cc3f6f8ac46}</h2>
341-
<button>{hero_cta}</button>
342-
</div>
343-
)}
344-
</Ditto>
345-
```
346-
347-
You can also iterate through the entire block (just as you can with any other object) to display each one.
348-
349-
```jsx
350-
<Ditto frameId="header" blockId="navigation">
351-
{(block) => {
352-
return Object.keys(block).map((id) => (
353-
<div key={block[id]}>{block[id]}</div>
354-
));
355-
}}
356-
</Ditto>
357-
```
358-
359-
### Example: Fetch Frame
360-
361-
You can also fetch an entire Block in Ditto at once by just specifying the `frameId`. With it, you can fetch specific blocks, or iterate through all blocks and containing IDs as needed.
362-
363-
```jsx
364-
<Ditto frameId="frame_601cc35d5be42cc3f6f8ad17">
365-
{(frame) => {
366-
return Object.keys(frame.blocks).map((blockId) => (
367-
<div className={style.footerCol} key={blockId}>
368-
{Object.keys(frame.blocks[blockId]).map((textId) => (
369-
<div className={style.link} key={textId}>
370-
{frame.blocks[blockId][textId]}
371-
</div>
372-
))}
373-
</div>
374-
));
375-
}}
376-
</Ditto>
377-
```
378-
379-
### Example: Filtering by Tags
380-
381-
If you want to filter the text fetched by properties contained in the project itself, you can specify parameters to the `filter` prop of the `Ditto` component. This currently only supports the Tags field in Ditto, but will be expanded in the future to filter on any other metadata properties.
382-
383-
```jsx
384-
// will only return text with the "TOP_NAV" tag
385-
<Ditto
386-
frameId="frame_601cc35d5be42cc3f6f8ad15"
387-
blockId="navigation"
388-
filters={{ tags: ["TOP_NAV"] }}
389-
>
390-
{(block) => {
391-
return Object.keys(block).map((id) => (
392-
<div className={style.link} key={block[id]}>
393-
{block[id]}
394-
</div>
395-
));
396-
}}
397-
</Ditto>
398-
```
399-
400-
---
401-
402373
## Source
403374

404375
The React provider takes structured JSON outputs from Ditto as the source. These can be linked and automatically updated via [our API/CLI](https://github.com/dittowords/cli), or exported manually via the Ditto web app.

example/package.json

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@
2424
"react-scripts": "link:../node_modules/react-scripts",
2525
"typescript": "link:../node_modules/typescript"
2626
},
27-
"devDependencies": {
28-
"@dittowords/cli": "^2.1.2"
29-
},
3027
"eslintConfig": {
3128
"extends": "react-app"
3229
},
@@ -41,5 +38,8 @@
4138
"last 1 firefox version",
4239
"last 1 safari version"
4340
]
41+
},
42+
"devDependencies": {
43+
"@dittowords/cli": "^3.0.0"
4444
}
4545
}

0 commit comments

Comments
 (0)