@adobe/design-data-spec 4.3.0 → 4.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/conformance/manifest-extensions/README.md +47 -31
- package/conformance/manifest-extensions/base/dataset.json +36 -3
- package/conformance/manifest-extensions/invalid/implementations-remove-no-match/expected-errors.json +10 -0
- package/conformance/manifest-extensions/invalid/implementations-remove-no-match/extensions/implementations/button.json +9 -0
- package/conformance/manifest-extensions/invalid/implementations-remove-no-match/manifest.json +5 -0
- package/conformance/manifest-extensions/invalid/implementations-row-missing-reference/expected-errors.json +7 -0
- package/conformance/manifest-extensions/invalid/implementations-row-missing-reference/extensions/implementations/button.json +9 -0
- package/conformance/manifest-extensions/invalid/implementations-row-missing-reference/manifest.json +5 -0
- package/conformance/manifest-extensions/invalid/implementations-unknown-component/expected-errors.json +10 -0
- package/conformance/manifest-extensions/invalid/implementations-unknown-component/extensions/implementations/nope.json +12 -0
- package/conformance/manifest-extensions/invalid/implementations-unknown-component/manifest.json +5 -0
- package/conformance/manifest-extensions/invalid/implementations-unknown-op/expected-errors.json +7 -0
- package/conformance/manifest-extensions/invalid/implementations-unknown-op/extensions/implementations/button.json +9 -0
- package/conformance/manifest-extensions/invalid/implementations-unknown-op/manifest.json +5 -0
- package/conformance/manifest-extensions/valid/implementations-later-file-wins/expected.json +19 -0
- package/conformance/manifest-extensions/valid/implementations-later-file-wins/extensions/implementations/a-button.json +11 -0
- package/conformance/manifest-extensions/valid/implementations-later-file-wins/extensions/implementations/b-button.json +11 -0
- package/conformance/manifest-extensions/valid/implementations-later-file-wins/manifest.json +5 -0
- package/conformance/manifest-extensions/valid/implementations-other-owner-untouched/expected.json +26 -0
- package/conformance/manifest-extensions/valid/implementations-other-owner-untouched/extensions/implementations/button.json +18 -0
- package/conformance/manifest-extensions/valid/implementations-other-owner-untouched/manifest.json +5 -0
- package/conformance/manifest-extensions/valid/implementations-platform-local-component/expected.json +12 -0
- package/conformance/manifest-extensions/valid/implementations-platform-local-component/extensions/components/tab-bar-ios.json +9 -0
- package/conformance/manifest-extensions/valid/implementations-platform-local-component/extensions/implementations/tab-bar-ios.json +10 -0
- package/conformance/manifest-extensions/valid/implementations-platform-local-component/manifest.json +5 -0
- package/conformance/manifest-extensions/valid/implementations-remove-row/expected.json +11 -0
- package/conformance/manifest-extensions/valid/implementations-remove-row/extensions/implementations/button.json +10 -0
- package/conformance/manifest-extensions/valid/implementations-remove-row/manifest.json +5 -0
- package/conformance/manifest-extensions/valid/implementations-upsert-foundation-row/expected.json +19 -0
- package/conformance/manifest-extensions/valid/implementations-upsert-foundation-row/extensions/implementations/button.json +12 -0
- package/conformance/manifest-extensions/valid/implementations-upsert-foundation-row/manifest.json +5 -0
- package/package.json +2 -1
- package/schemas/component.schema.json +8 -3
- package/schemas/implementation-mapping.schema.json +69 -0
- package/schemas/manifest.schema.json +20 -0
- package/spec/authoring-workflow.md +1 -0
- package/spec/component-format.md +43 -20
- package/spec/index.md +2 -0
- package/spec/manifest.md +101 -28
- package/spec/taxonomy.md +2 -0
|
@@ -4,12 +4,14 @@ Exercises the Layer 2 platform manifest's `extensions/` **directory** loader
|
|
|
4
4
|
(`packages/design-data-spec/spec/manifest.md#extensions-directory`): a sibling
|
|
5
5
|
`extensions/` tree (or a custom name via the manifest's `extensionsDir` field)
|
|
6
6
|
whose category subdirectories (`tokens/`, `components/`, `fields/`,
|
|
7
|
-
`guidelines/`, `mode-sets/`, `platform-extensions/`, `relationships
|
|
7
|
+
`guidelines/`, `mode-sets/`, `platform-extensions/`, `relationships/`,
|
|
8
|
+
`implementations/`) are discovered,
|
|
8
9
|
glob+merged in sorted path order, per-fragment schema-validated, and spliced
|
|
9
10
|
into the manifest before it's applied to the graph.
|
|
10
11
|
|
|
11
12
|
* `base/dataset.json` — a shared minimal seed graph (three foundation tokens:
|
|
12
|
-
`btn-bg`, `btn-fg`, `chk-bg` on the `button`/`checkbox` components
|
|
13
|
+
`btn-bg`, `btn-fg`, `chk-bg` on the `button`/`checkbox` components, plus a
|
|
14
|
+
foundation `button` component with two default `implementations` rows), loaded
|
|
13
15
|
once per case before that case's `manifest.json` is applied via
|
|
14
16
|
`apply_configured`.
|
|
15
17
|
* `valid/<case>/` — `manifest.json` + an `extensions/` (or custom-named) tree
|
|
@@ -19,13 +21,18 @@ into the manifest before it's applied to the graph.
|
|
|
19
21
|
{
|
|
20
22
|
"relationships": {
|
|
21
23
|
"byUuid": { "<uuid>": { "count": 1, "value": "8px" } },
|
|
22
|
-
"absent": ["<uuid>"]
|
|
24
|
+
"absent": ["<uuid>"],
|
|
23
25
|
},
|
|
24
26
|
"components": { "present": ["tab-bar-ios"] },
|
|
25
27
|
"fields": { "present": ["hapticStyle"] },
|
|
26
28
|
"modeSets": { "present": ["interfaceLevel"] },
|
|
27
29
|
"guidelines": { "present": ["ios-haptics"] },
|
|
28
|
-
"tokens": { "orderByUuid": ["<uuid-1>", "<uuid-2>"] }
|
|
30
|
+
"tokens": { "orderByUuid": ["<uuid-1>", "<uuid-2>"] },
|
|
31
|
+
"implementations": {
|
|
32
|
+
"<component>": [
|
|
33
|
+
/* exact merged rows */
|
|
34
|
+
],
|
|
35
|
+
},
|
|
29
36
|
}
|
|
30
37
|
```
|
|
31
38
|
A case that only needs to prove "loads clean" uses `{}`.
|
|
@@ -37,30 +44,39 @@ Rust SDK drives these fixtures in `sdk/core/src/lib.rs` via the
|
|
|
37
44
|
`manifest_extensions_conformance` (pass/fail + error message matching) and
|
|
38
45
|
`manifest_extensions_behavior` (post-apply graph predicates) test modules.
|
|
39
46
|
|
|
40
|
-
| Case
|
|
41
|
-
|
|
|
42
|
-
| `valid/injects-component`
|
|
43
|
-
| `valid/injects-platform-extension`
|
|
44
|
-
| `valid/injects-field`
|
|
45
|
-
| `valid/injects-guideline`
|
|
46
|
-
| `valid/injects-mode-set`
|
|
47
|
-
| `valid/injects-relationship`
|
|
48
|
-
| `valid/override-relationship-by-uuid`
|
|
49
|
-
| `valid/plain-add-uuid-collision-append`
|
|
50
|
-
| `valid/remove-relationship-by-uuid`
|
|
51
|
-
| `valid/tokens-sorted-order`
|
|
52
|
-
| `valid/later-file-wins`
|
|
53
|
-
| `valid/custom-extensions-dir`
|
|
54
|
-
| `valid/override-entry-skips-schema-validation`
|
|
55
|
-
| `
|
|
56
|
-
| `
|
|
57
|
-
| `
|
|
58
|
-
| `
|
|
59
|
-
| `
|
|
60
|
-
| `invalid/
|
|
61
|
-
| `invalid/
|
|
62
|
-
| `invalid/
|
|
63
|
-
| `invalid/
|
|
64
|
-
| `invalid/
|
|
65
|
-
| `invalid/
|
|
66
|
-
| `invalid/
|
|
47
|
+
| Case | Intent |
|
|
48
|
+
| ------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| `valid/injects-component` | A `components/` fragment is injected as a Platform-layer component. |
|
|
50
|
+
| `valid/injects-platform-extension` | A `platform-extensions/` fragment is injected. |
|
|
51
|
+
| `valid/injects-field` | A `fields/` fragment is injected. |
|
|
52
|
+
| `valid/injects-guideline` | A `guidelines/` fragment is injected. |
|
|
53
|
+
| `valid/injects-mode-set` | A `mode-sets/` fragment is injected (declare-or-replace by name). |
|
|
54
|
+
| `valid/injects-relationship` | A `relationships/` plain-add fragment is injected. |
|
|
55
|
+
| `valid/override-relationship-by-uuid` | An `op: "override"` entry replaces a plain add sharing its `uuid`, regardless of file sort order. |
|
|
56
|
+
| `valid/plain-add-uuid-collision-append` | Two plain adds sharing a `uuid` both append rather than one overwriting the other. |
|
|
57
|
+
| `valid/remove-relationship-by-uuid` | An `op: "remove"` entry deletes the matching relationship. |
|
|
58
|
+
| `valid/tokens-sorted-order` | Multiple `tokens/*.tokens.json` files concatenate in sorted path order. |
|
|
59
|
+
| `valid/later-file-wins` | Two `components/` fragments declaring the same component name dedupe to one, later file wins. |
|
|
60
|
+
| `valid/custom-extensions-dir` | The manifest's `extensionsDir` field is honored in place of the default `extensions/` name. |
|
|
61
|
+
| `valid/override-entry-skips-schema-validation` | An `op: "override"` relationship entry is not schema-validated against `relationship.schema.json` (only plain adds are). |
|
|
62
|
+
| `valid/implementations-upsert-foundation-row` | An `implementations/` row replaces the foundation default sharing its `importPath` and is stamped with the manifest `platform`. |
|
|
63
|
+
| `valid/implementations-later-file-wins` | Two fragments upserting the same stamped row dedupe by `implementation` id; the later file wins. |
|
|
64
|
+
| `valid/implementations-remove-row` | An `op: "remove"` selector deletes the matching foundation default. |
|
|
65
|
+
| `valid/implementations-platform-local-component` | A fragment may target a component added by the same manifest's `components/`. |
|
|
66
|
+
| `valid/implementations-other-owner-untouched` | A row stamped with a different `implementation` id is never matched by another owner's upsert. |
|
|
67
|
+
| `invalid/override-missing-uuid` | An `op: "override"` relationship entry missing `uuid` fails loudly. |
|
|
68
|
+
| `invalid/unknown-term-id` | A `platform-extensions/` fragment referencing a non-existent `termId` fails loudly. |
|
|
69
|
+
| `invalid/component-missing-name` | A `components/` fragment missing `name` fails Layer 1 fragment schema validation. |
|
|
70
|
+
| `invalid/field-invalid-kind` | A `fields/` fragment with an invalid `kind` enum value fails schema validation. |
|
|
71
|
+
| `invalid/guideline-invalid-category` | A `guidelines/` fragment with an invalid `category` enum value fails schema validation. |
|
|
72
|
+
| `invalid/mode-set-missing-default` | A `mode-sets/` fragment missing the required `default` field fails Layer 1 fragment schema validation. |
|
|
73
|
+
| `invalid/platform-extension-missing-extends` | A `platform-extensions/` fragment missing `extends` fails schema validation. |
|
|
74
|
+
| `invalid/token-invalid-uuid` | A `tokens/*.tokens.json` fragment with a malformed `uuid` fails schema validation. |
|
|
75
|
+
| `invalid/relationship-missing-scope` | A `relationships/` plain-add fragment missing `scope` fails schema validation. |
|
|
76
|
+
| `invalid/extensions-dir-parent-traversal` | `extensionsDir` containing a `..` component is rejected. |
|
|
77
|
+
| `invalid/extensions-dir-absolute-path` | An absolute `extensionsDir` path is rejected. |
|
|
78
|
+
| `invalid/unknown-subdir-name` | An unrecognized subdirectory directly under `extensions/` (not one of the known categories) is rejected by name. |
|
|
79
|
+
| `invalid/implementations-unknown-component` | An `implementations/` fragment naming a component absent from the catalog fails loudly. |
|
|
80
|
+
| `invalid/implementations-remove-no-match` | An `op: "remove"` matching no owned row fails loudly. |
|
|
81
|
+
| `invalid/implementations-row-missing-reference` | A row with neither `package` nor `importPath` fails schema validation. |
|
|
82
|
+
| `invalid/implementations-unknown-op` | An `op` other than `"remove"` fails schema validation. |
|
|
@@ -2,21 +2,54 @@
|
|
|
2
2
|
"tokens": [
|
|
3
3
|
{
|
|
4
4
|
"key": "btn-bg",
|
|
5
|
-
"name": {
|
|
5
|
+
"name": {
|
|
6
|
+
"property": "background-color",
|
|
7
|
+
"component": "button"
|
|
8
|
+
},
|
|
6
9
|
"value": "#aaa",
|
|
7
10
|
"uuid": "u-btn-bg"
|
|
8
11
|
},
|
|
9
12
|
{
|
|
10
13
|
"key": "btn-fg",
|
|
11
|
-
"name": {
|
|
14
|
+
"name": {
|
|
15
|
+
"property": "color",
|
|
16
|
+
"component": "button"
|
|
17
|
+
},
|
|
12
18
|
"value": "#111",
|
|
13
19
|
"uuid": "u-btn-fg"
|
|
14
20
|
},
|
|
15
21
|
{
|
|
16
22
|
"key": "chk-bg",
|
|
17
|
-
"name": {
|
|
23
|
+
"name": {
|
|
24
|
+
"property": "background-color",
|
|
25
|
+
"component": "checkbox"
|
|
26
|
+
},
|
|
18
27
|
"value": "#bbb",
|
|
19
28
|
"uuid": "u-chk-bg"
|
|
20
29
|
}
|
|
30
|
+
],
|
|
31
|
+
"components": [
|
|
32
|
+
{
|
|
33
|
+
"$id": "https://example.com/components/button",
|
|
34
|
+
"name": "button",
|
|
35
|
+
"displayName": "Button",
|
|
36
|
+
"meta": {
|
|
37
|
+
"category": "actions",
|
|
38
|
+
"documentationUrl": "https://example.com"
|
|
39
|
+
},
|
|
40
|
+
"implementations": [
|
|
41
|
+
{
|
|
42
|
+
"platform": "web",
|
|
43
|
+
"componentName": "Button",
|
|
44
|
+
"package": "@react-spectrum/s2"
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
"platform": "web",
|
|
48
|
+
"componentName": "Button",
|
|
49
|
+
"importPath": "@adobe/spectrum-wc/components/button",
|
|
50
|
+
"notes": "Spectrum 2 web component custom element: swc-button."
|
|
51
|
+
}
|
|
52
|
+
]
|
|
53
|
+
}
|
|
21
54
|
]
|
|
22
55
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"implementations": {
|
|
3
|
+
"button": [
|
|
4
|
+
{
|
|
5
|
+
"platform": "web",
|
|
6
|
+
"componentName": "Button",
|
|
7
|
+
"package": "@react-spectrum/s2",
|
|
8
|
+
"notes": "second",
|
|
9
|
+
"implementation": "react-spectrum"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"platform": "web",
|
|
13
|
+
"componentName": "Button",
|
|
14
|
+
"importPath": "@adobe/spectrum-wc/components/button",
|
|
15
|
+
"notes": "Spectrum 2 web component custom element: swc-button."
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
package/conformance/manifest-extensions/valid/implementations-other-owner-untouched/expected.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"implementations": {
|
|
3
|
+
"button": [
|
|
4
|
+
{
|
|
5
|
+
"platform": "web",
|
|
6
|
+
"componentName": "Button",
|
|
7
|
+
"package": "@react-spectrum/s2",
|
|
8
|
+
"implementation": "react-spectrum",
|
|
9
|
+
"notes": "declared by another owner"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"platform": "web",
|
|
13
|
+
"componentName": "Button",
|
|
14
|
+
"importPath": "@adobe/spectrum-wc/components/button",
|
|
15
|
+
"notes": "Spectrum 2 web component custom element: swc-button."
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"platform": "web",
|
|
19
|
+
"componentName": "Button",
|
|
20
|
+
"package": "@react-spectrum/s2",
|
|
21
|
+
"implementation": "web-components",
|
|
22
|
+
"notes": "web-components row with the same package"
|
|
23
|
+
}
|
|
24
|
+
]
|
|
25
|
+
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"component": "button",
|
|
3
|
+
"implementations": [
|
|
4
|
+
{
|
|
5
|
+
"platform": "web",
|
|
6
|
+
"componentName": "Button",
|
|
7
|
+
"package": "@react-spectrum/s2",
|
|
8
|
+
"implementation": "react-spectrum",
|
|
9
|
+
"notes": "declared by another owner"
|
|
10
|
+
},
|
|
11
|
+
{
|
|
12
|
+
"platform": "web",
|
|
13
|
+
"componentName": "Button",
|
|
14
|
+
"package": "@react-spectrum/s2",
|
|
15
|
+
"notes": "web-components row with the same package"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
package/conformance/manifest-extensions/valid/implementations-upsert-foundation-row/expected.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"implementations": {
|
|
3
|
+
"button": [
|
|
4
|
+
{
|
|
5
|
+
"platform": "web",
|
|
6
|
+
"componentName": "Button",
|
|
7
|
+
"package": "@react-spectrum/s2"
|
|
8
|
+
},
|
|
9
|
+
{
|
|
10
|
+
"platform": "web",
|
|
11
|
+
"componentName": "Button",
|
|
12
|
+
"package": "@adobe/spectrum-wc",
|
|
13
|
+
"importPath": "@adobe/spectrum-wc/components/button",
|
|
14
|
+
"notes": "Custom element: swc-button.",
|
|
15
|
+
"implementation": "web-components"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/design-data-spec",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "Design Data Specification — prose, JSON Schemas, rule catalog, and conformance fixtures for the design data format",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"repository": {
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"./schemas/manifest.schema.json": "./schemas/manifest.schema.json",
|
|
27
27
|
"./schemas/value-types/color.schema.json": "./schemas/value-types/color.schema.json",
|
|
28
28
|
"./schemas/component.schema.json": "./schemas/component.schema.json",
|
|
29
|
+
"./schemas/implementation-mapping.schema.json": "./schemas/implementation-mapping.schema.json",
|
|
29
30
|
"./schemas/anatomy-part.schema.json": "./schemas/anatomy-part.schema.json",
|
|
30
31
|
"./schemas/state-declaration.schema.json": "./schemas/state-declaration.schema.json",
|
|
31
32
|
"./rules/rules.yaml": "./rules/rules.yaml",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"items": {
|
|
43
43
|
"$ref": "#/$defs/implementation"
|
|
44
44
|
},
|
|
45
|
-
"description": "Known platform implementations of this component. Foundation
|
|
45
|
+
"description": "Known platform implementations of this component. Foundation data carries canonical default mappings; a platform manifest refines its own rows through extensions/implementations/. See spec/component-format.md#implementations."
|
|
46
46
|
},
|
|
47
47
|
"options": {
|
|
48
48
|
"$ref": "#/$defs/optionsMap"
|
|
@@ -115,6 +115,11 @@
|
|
|
115
115
|
"minLength": 1,
|
|
116
116
|
"description": "Target platform identifier (for example, 'web', 'ios', or 'android'). Multiple implementations may target the same platform when they have distinct packages."
|
|
117
117
|
},
|
|
118
|
+
"implementation": {
|
|
119
|
+
"type": "string",
|
|
120
|
+
"pattern": "^[a-z][a-z0-9-]*$",
|
|
121
|
+
"description": "Implementation project id from the platform-implementations registry (for example, 'react-spectrum' or 'web-components'). Distinguishes implementations that share a `platform` device target. A platform manifest stamps its own `platform` id here when merging extensions/implementations/ entries that omit it."
|
|
122
|
+
},
|
|
118
123
|
"componentName": {
|
|
119
124
|
"type": "string",
|
|
120
125
|
"minLength": 1,
|
|
@@ -123,7 +128,7 @@
|
|
|
123
128
|
"importPath": {
|
|
124
129
|
"type": "string",
|
|
125
130
|
"minLength": 1,
|
|
126
|
-
"description": "Importable module or source path for a platform implementation."
|
|
131
|
+
"description": "Importable module or source path for a platform implementation. When `package` is also set, this SHOULD be a subpath export of that package."
|
|
127
132
|
},
|
|
128
133
|
"package": {
|
|
129
134
|
"type": "string",
|
|
@@ -135,7 +140,7 @@
|
|
|
135
140
|
"description": "Optional implementation-specific usage or mapping notes."
|
|
136
141
|
}
|
|
137
142
|
},
|
|
138
|
-
"
|
|
143
|
+
"anyOf": [
|
|
139
144
|
{
|
|
140
145
|
"required": ["importPath"]
|
|
141
146
|
},
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"$id": "https://opensource.adobe.com/spectrum-design-data/schemas/v0/implementation-mapping.schema.json",
|
|
4
|
+
"title": "Platform implementation mapping",
|
|
5
|
+
"description": "Layer 1 schema for one platform manifest extensions/implementations/ fragment: the platform's own implementation rows for a single component, merged into that component's `implementations` array. See spec/manifest.md#extensionsimplementations.",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"required": ["component", "implementations"],
|
|
8
|
+
"properties": {
|
|
9
|
+
"$schema": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"format": "uri"
|
|
12
|
+
},
|
|
13
|
+
"component": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"pattern": "^[a-z][a-z0-9-]*$",
|
|
16
|
+
"description": "Name of the component (foundation or platform-local) whose `implementations` this fragment refines."
|
|
17
|
+
},
|
|
18
|
+
"implementations": {
|
|
19
|
+
"type": "array",
|
|
20
|
+
"minItems": 1,
|
|
21
|
+
"items": {
|
|
22
|
+
"if": {
|
|
23
|
+
"required": ["op"]
|
|
24
|
+
},
|
|
25
|
+
"then": {
|
|
26
|
+
"$ref": "#/$defs/removeEntry"
|
|
27
|
+
},
|
|
28
|
+
"else": {
|
|
29
|
+
"$ref": "component.schema.json#/$defs/implementation"
|
|
30
|
+
}
|
|
31
|
+
},
|
|
32
|
+
"description": "Rows to upsert (implementation objects) or remove (`op: \"remove\"` selectors), applied in order."
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"additionalProperties": false,
|
|
36
|
+
"$defs": {
|
|
37
|
+
"removeEntry": {
|
|
38
|
+
"type": "object",
|
|
39
|
+
"description": "Removes every existing row of the component whose fields equal each selector field given here.",
|
|
40
|
+
"required": ["op", "componentName"],
|
|
41
|
+
"properties": {
|
|
42
|
+
"op": {
|
|
43
|
+
"const": "remove"
|
|
44
|
+
},
|
|
45
|
+
"platform": {
|
|
46
|
+
"type": "string",
|
|
47
|
+
"minLength": 1
|
|
48
|
+
},
|
|
49
|
+
"implementation": {
|
|
50
|
+
"type": "string",
|
|
51
|
+
"pattern": "^[a-z][a-z0-9-]*$"
|
|
52
|
+
},
|
|
53
|
+
"componentName": {
|
|
54
|
+
"type": "string",
|
|
55
|
+
"minLength": 1
|
|
56
|
+
},
|
|
57
|
+
"package": {
|
|
58
|
+
"type": "string",
|
|
59
|
+
"minLength": 1
|
|
60
|
+
},
|
|
61
|
+
"importPath": {
|
|
62
|
+
"type": "string",
|
|
63
|
+
"minLength": 1
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
"additionalProperties": false
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
@@ -14,6 +14,21 @@
|
|
|
14
14
|
"minLength": 1,
|
|
15
15
|
"description": "Pin to a foundation release (semver or tag)."
|
|
16
16
|
},
|
|
17
|
+
"platform": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"minLength": 1,
|
|
20
|
+
"description": "Machine-readable platform implementation id (e.g. \"react-spectrum\", \"web-components\", \"ios\"), matching an id in the platform-implementations registry. Optional: a manifest MAY be anonymous (e.g. a single-platform repo where identity is implicit), but SHOULD declare it once the manifest is relocatable (fetched remotely, or one of several manifests in the same repo)."
|
|
21
|
+
},
|
|
22
|
+
"platformVersion": {
|
|
23
|
+
"type": "string",
|
|
24
|
+
"minLength": 1,
|
|
25
|
+
"description": "Human-readable description of the platform implementation this manifest targets, e.g. \"React Spectrum 3.x\" or \"Spectrum Web Components 0.x+\". Distinct from `foundationVersion` (the pinned foundation release)."
|
|
26
|
+
},
|
|
27
|
+
"repository": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"minLength": 1,
|
|
30
|
+
"description": "URL of the repository that owns (or, during incubation, will eventually own) this platform manifest, e.g. \"https://github.com/adobe/react-spectrum\"."
|
|
31
|
+
},
|
|
17
32
|
"include": {
|
|
18
33
|
"type": "array",
|
|
19
34
|
"items": {
|
|
@@ -138,6 +153,11 @@
|
|
|
138
153
|
"type": "string"
|
|
139
154
|
},
|
|
140
155
|
"description": "Map of full term to abbreviated form, applied after ordering and before casing."
|
|
156
|
+
},
|
|
157
|
+
"prefix": {
|
|
158
|
+
"type": "string",
|
|
159
|
+
"minLength": 1,
|
|
160
|
+
"description": "Literal string prepended to the fully-formatted token name (after casing/delimiter are applied), unaffected by `casing` itself. For platform naming conventions that wrap the token name rather than reshape it, e.g. CSS custom properties (`--spectrum-`) or other namespaced identifier prefixes."
|
|
141
161
|
}
|
|
142
162
|
},
|
|
143
163
|
"additionalProperties": false
|
|
@@ -20,6 +20,7 @@ The source-of-truth direction is already normative in [Evolution](evolution.md#l
|
|
|
20
20
|
|
|
21
21
|
* Specifying the *output format* of generated artifacts. Legacy format mapping is defined in [Evolution — Legacy format contract](evolution.md#legacy-format-contract); DTCG and StyleDictionary outputs are deferred (RFC [#627](https://github.com/adobe/spectrum-design-data/discussions/627)).
|
|
22
22
|
* Specifying the *consumer-facing API* of published packages (`@adobe/spectrum-tokens`, platform SDKs). Those are separately governed.
|
|
23
|
+
* Restating the full semantics of external implementation contracts already owned by their native standards or package ecosystems. This spec links to authoritative sources instead of duplicating their normative rules.
|
|
23
24
|
* Specifying the *UI* of the authoring tools; this document defines behavioral contracts, not user-interface design.
|
|
24
25
|
* Multi-user collaboration, permissions models, and Figma sync direction (open questions in RFC [#625](https://github.com/adobe/spectrum-design-data/discussions/625)).
|
|
25
26
|
|
package/spec/component-format.md
CHANGED
|
@@ -6,6 +6,8 @@ This document defines the normative **component declaration** object: identity (
|
|
|
6
6
|
|
|
7
7
|
Component declarations close the structural gap between the token name-object's `component`, `variant`, `anatomy`, and `state` fields and the declared surface of each component. Before this chapter, a token referencing `component: "button"` with `variant: "foo"` was undetectable as invalid because no machine-readable component contract existed in the same spec. After this chapter, validators enforce cross-reference rules (see [SPEC rules](#spec-rules)).
|
|
8
8
|
|
|
9
|
+
This chapter defines the Design Data contract for a component. It intentionally does not restate the full platform-native component API, story/example-format semantics, or other standards already owned elsewhere. When another authoritative specification already defines an implementation contract or format, this document points to that source instead of duplicating its normative rules.
|
|
10
|
+
|
|
9
11
|
Scoped under [RFC-A — Component Contract in Design Data Spec](https://github.com/adobe/spectrum-design-data/discussions/832). See also [rfc-coordination.md](../docs/rfc-coordination.md).
|
|
10
12
|
|
|
11
13
|
## Document shape
|
|
@@ -82,34 +84,44 @@ where `{name}` matches the component's `name` field.
|
|
|
82
84
|
## Implementations
|
|
83
85
|
|
|
84
86
|
`implementations` declares the published platform implementations corresponding
|
|
85
|
-
to this design-system component
|
|
86
|
-
|
|
87
|
-
|
|
87
|
+
to this design-system component, so consumers such as Code Connect generators
|
|
88
|
+
can resolve an implementation without platform-specific configuration.
|
|
89
|
+
|
|
90
|
+
Each entry **MUST** contain `platform` and `componentName`, plus at least one
|
|
91
|
+
implementation reference: `package` for a published package and/or
|
|
92
|
+
`importPath` for an importable module or source path. When both are present,
|
|
93
|
+
`importPath` **SHOULD** be a subpath export of `package`. `notes` is optional
|
|
94
|
+
context for consumers.
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
different implementations for that platform.
|
|
96
|
+
`platform` is a device target (`web`, `ios`, `android`), so several
|
|
97
|
+
implementations may share it. The optional `implementation` field names the
|
|
98
|
+
implementation project from the platform-implementations registry (for example
|
|
99
|
+
`react-spectrum` or `web-components`) to tell them apart.
|
|
94
100
|
|
|
95
101
|
```json
|
|
96
102
|
"implementations": [
|
|
97
103
|
{
|
|
98
104
|
"platform": "web",
|
|
105
|
+
"implementation": "web-components",
|
|
99
106
|
"componentName": "Button",
|
|
100
|
-
"package": "@spectrum-
|
|
107
|
+
"package": "@adobe/spectrum-wc",
|
|
108
|
+
"importPath": "@adobe/spectrum-wc/components/button"
|
|
101
109
|
}
|
|
102
110
|
]
|
|
103
111
|
```
|
|
104
112
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
113
|
+
### Layering
|
|
114
|
+
|
|
115
|
+
Foundation component data carries canonical **default** rows. A platform
|
|
116
|
+
manifest refines its own rows through
|
|
117
|
+
[`extensions/implementations/`](manifest.md#extensionsimplementations):
|
|
118
|
+
upserting rows it owns and removing stale ones, without restating the rest of
|
|
119
|
+
the component. Rows owned by another implementation are left untouched, so the
|
|
120
|
+
merged catalog still lists every implementation of the component.
|
|
109
121
|
|
|
110
122
|
## Options
|
|
111
123
|
|
|
112
|
-
The `options` block declares the component's API surface — the configurable properties that affect its appearance or behavior. It
|
|
124
|
+
The `options` block declares the component's API surface — the configurable properties that affect its appearance or behavior. It is the Design Data contract for the component surface that this repo validates; it does not duplicate the entire implementation-owned API schema. For exhaustive platform-specific semantics, follow the authoritative implementation contract instead of restating it here.
|
|
113
125
|
|
|
114
126
|
**NORMATIVE:** `options` **MUST** be a JSON object. Each key is an option name; each value is an **option descriptor**.
|
|
115
127
|
|
|
@@ -424,13 +436,18 @@ A complete button component declaration:
|
|
|
424
436
|
}
|
|
425
437
|
],
|
|
426
438
|
"anatomy": [
|
|
427
|
-
{ "name": "icon",
|
|
439
|
+
{ "name": "icon", "description": "Leading icon." },
|
|
428
440
|
{ "name": "label", "description": "Button text.", "required": true }
|
|
429
441
|
],
|
|
430
442
|
"states": [
|
|
431
|
-
{ "name": "hover",
|
|
432
|
-
{
|
|
433
|
-
|
|
443
|
+
{ "name": "hover", "trigger": "interaction", "precedence": 50 },
|
|
444
|
+
{
|
|
445
|
+
"name": "focus",
|
|
446
|
+
"trigger": "interaction",
|
|
447
|
+
"precedence": 60,
|
|
448
|
+
"layered": true
|
|
449
|
+
},
|
|
450
|
+
{ "name": "disabled", "trigger": "prop", "precedence": 100 }
|
|
434
451
|
],
|
|
435
452
|
"lifecycle": {
|
|
436
453
|
"introduced": "1.0.0-draft"
|
|
@@ -446,7 +463,10 @@ A complete button component declaration:
|
|
|
446
463
|
{
|
|
447
464
|
"name": "button",
|
|
448
465
|
"displayName": "Button",
|
|
449
|
-
"meta": {
|
|
466
|
+
"meta": {
|
|
467
|
+
"category": "actions",
|
|
468
|
+
"documentationUrl": "https://spectrum.adobe.com/page/button/"
|
|
469
|
+
},
|
|
450
470
|
"accessibility": {
|
|
451
471
|
"role": "button",
|
|
452
472
|
"intents": ["trigger"],
|
|
@@ -477,7 +497,10 @@ A complete button component declaration:
|
|
|
477
497
|
{
|
|
478
498
|
"name": "button",
|
|
479
499
|
"displayName": "Button",
|
|
480
|
-
"meta": {
|
|
500
|
+
"meta": {
|
|
501
|
+
"category": "actions",
|
|
502
|
+
"documentationUrl": "https://spectrum.adobe.com/page/button/"
|
|
503
|
+
},
|
|
481
504
|
"documentBlocks": [
|
|
482
505
|
{
|
|
483
506
|
"type": "purpose",
|
package/spec/index.md
CHANGED
|
@@ -30,6 +30,8 @@ The specification defines:
|
|
|
30
30
|
16. **Authoring workflow** — normative contract for authoring design data via tooling: authoritative source location, lifecycle operations (create / edit / deprecate / rename / alias-rewire / mode-set management), taxonomy-aware decomposition requirement, and output-generation obligations ([Authoring workflow](authoring-workflow.md)).
|
|
31
31
|
17. **Relationship format** — Component/Token Relationship (CTR): the anonymous-token entity unifying `tokenBindings` and token name-object scope fields, explicit relationship context, options validation, and interim legacy-compatibility fields ([Relationship format](relationship-format.md)).
|
|
32
32
|
|
|
33
|
+
This specification intentionally defines the Design Data-owned contract and links to external standards for platform-native implementation semantics instead of restating those contracts as normative local rules. The repository owns taxonomy, validation, lifecycle, and schema rules; the authoritative source for native format behavior remains the external standard it describes.
|
|
34
|
+
|
|
33
35
|
## Conformance
|
|
34
36
|
|
|
35
37
|
The key words **MUST**, **MUST NOT**, **SHOULD**, **SHOULD NOT**, **MAY**, and **OPTIONAL** in this specification are to be interpreted as described in [BCP 14](https://www.rfc-editor.org/info/bcp14) \[[RFC2119](https://www.rfc-editor.org/rfc/rfc2119.html)] \[[RFC8174](https://www.rfc-editor.org/rfc/rfc8174.html)] when, and only when, they appear in all capitals, as shown here.
|
package/spec/manifest.md
CHANGED
|
@@ -8,25 +8,26 @@ This document defines the **platform manifest**: how a platform implementation r
|
|
|
8
8
|
|
|
9
9
|
The manifest supports a fixed, enumerated set of operations against the foundation — it does **not** allow overriding, aliasing, or removing arbitrary foundation artifacts. Support is concentrated on tokens; translations and schemas have no manifest-level override mechanism at all.
|
|
10
10
|
|
|
11
|
-
| Operation | Supported? | Field | Applies to
|
|
12
|
-
| --------------------------------------------------- | ------------------------------------------------------------ | --------------------------------- |
|
|
13
|
-
| Remove / exclude | Yes | `exclude` | Tokens only
|
|
14
|
-
| Include / whitelist | Yes | `include` | Tokens only
|
|
15
|
-
| Override value (type-preserving) | Yes | `overrides[].value` | Tokens only
|
|
16
|
-
| Override → re-alias | Yes | `overrides[].$ref` | Tokens only
|
|
17
|
-
| Add new tokens (may alias via `$ref`) | Yes | `extensions/tokens/` | Tokens
|
|
18
|
-
| Add / replace components | Yes | `extensions/components/` | Components
|
|
19
|
-
| Add / replace field declarations | Yes | `extensions/fields/` | Fields
|
|
20
|
-
| Add / replace guideline documents | Yes | `extensions/guidelines/` | Guidelines
|
|
21
|
-
| Declare / replace platform-local mode set | Yes | `extensions/mode-sets/` | Mode sets
|
|
22
|
-
| Add / remove / retarget a single mode; remove a set | Yes | `extensions/mode-sets/` (`op`) | Mode sets
|
|
23
|
-
| Add relationships/CTRs; override/remove by `uuid` | Yes | `extensions/relationships/` | Relationships (CTRs)
|
|
24
|
-
| Add / remove naming exceptions | Yes | `namingExceptions` | Naming validation
|
|
25
|
-
| Annotate existing terminology (cannot add new ids) | Yes | `extensions/platform-extensions/` | Existing registry ids
|
|
26
|
-
|
|
|
27
|
-
|
|
|
28
|
-
|
|
|
29
|
-
| Override
|
|
11
|
+
| Operation | Supported? | Field | Applies to |
|
|
12
|
+
| --------------------------------------------------- | ------------------------------------------------------------ | --------------------------------- | --------------------------- |
|
|
13
|
+
| Remove / exclude | Yes | `exclude` | Tokens only |
|
|
14
|
+
| Include / whitelist | Yes | `include` | Tokens only |
|
|
15
|
+
| Override value (type-preserving) | Yes | `overrides[].value` | Tokens only |
|
|
16
|
+
| Override → re-alias | Yes | `overrides[].$ref` | Tokens only |
|
|
17
|
+
| Add new tokens (may alias via `$ref`) | Yes | `extensions/tokens/` | Tokens |
|
|
18
|
+
| Add / replace components | Yes | `extensions/components/` | Components |
|
|
19
|
+
| Add / replace field declarations | Yes | `extensions/fields/` | Fields |
|
|
20
|
+
| Add / replace guideline documents | Yes | `extensions/guidelines/` | Guidelines |
|
|
21
|
+
| Declare / replace platform-local mode set | Yes | `extensions/mode-sets/` | Mode sets |
|
|
22
|
+
| Add / remove / retarget a single mode; remove a set | Yes | `extensions/mode-sets/` (`op`) | Mode sets |
|
|
23
|
+
| Add relationships/CTRs; override/remove by `uuid` | Yes | `extensions/relationships/` | Relationships (CTRs) |
|
|
24
|
+
| Add / remove naming exceptions | Yes | `namingExceptions` | Naming validation |
|
|
25
|
+
| Annotate existing terminology (cannot add new ids) | Yes | `extensions/platform-extensions/` | Existing registry ids |
|
|
26
|
+
| Upsert / remove own implementation mappings | Yes | `extensions/implementations/` | Component `implementations` |
|
|
27
|
+
| Restrict allowed mode-set values | Yes | `modeSetRestrictions` | Mode sets |
|
|
28
|
+
| Reformat name serialization | Schema-declared only, not yet applied by the reference SDK | `formatting` | Token name strings |
|
|
29
|
+
| Override/remove/alias translations | No | — | — |
|
|
30
|
+
| Override Layer-1 schemas | No (decided; see [spike](manifest-schema-override-spike.md)) | — | — |
|
|
30
31
|
|
|
31
32
|
## Manifest document
|
|
32
33
|
|
|
@@ -41,15 +42,18 @@ A manifest **MUST** conform to [`manifest.schema.json`](../schemas/manifest.sche
|
|
|
41
42
|
|
|
42
43
|
## Optional fields
|
|
43
44
|
|
|
44
|
-
| Field | Type | Description
|
|
45
|
-
| --------------------- | --------------- |
|
|
46
|
-
| `
|
|
47
|
-
| `
|
|
48
|
-
| `
|
|
49
|
-
| `
|
|
50
|
-
| `
|
|
51
|
-
| `
|
|
52
|
-
| `
|
|
45
|
+
| Field | Type | Description |
|
|
46
|
+
| --------------------- | --------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
47
|
+
| `platform` | string | Machine-readable platform implementation id (e.g. `"react-spectrum"`, `"web-components"`, `"ios"`), matching an id in the platform-implementations registry. See [Identity fields](#identity-fields) below. |
|
|
48
|
+
| `platformVersion` | string | Human-readable description of the platform implementation, e.g. `"React Spectrum 3.x"`. Distinct from `foundationVersion`. |
|
|
49
|
+
| `repository` | string | URL of the repository that owns (or will eventually own) this platform manifest. |
|
|
50
|
+
| `include` | array of string | Semantic **queries** selecting subsets of foundation tokens to materialize. |
|
|
51
|
+
| `exclude` | array of string | Queries removing tokens from the included set. |
|
|
52
|
+
| `overrides` | array of object | Typed overrides; each entry **MUST** preserve the target token’s **value type**. |
|
|
53
|
+
| `extensionsDir` | string | Path (relative to the manifest) to the platform's `extensions/` directory. Default: `"extensions"`. See [`extensions/` directory](#extensions-directory) below. |
|
|
54
|
+
| `namingExceptions` | object | Platform-local overlay on the base naming-exceptions set: names to add and/or remove for this platform's naming validation. |
|
|
55
|
+
| `formatting` | object | Rules for serializing structured name objects into platform-specific token name strings. |
|
|
56
|
+
| `modeSetRestrictions` | object | Mode set restrictions for this platform; see [Mode Sets — Platform restrictions](mode-sets.md#platform-restrictions). |
|
|
53
57
|
|
|
54
58
|
### `include` / `exclude`
|
|
55
59
|
|
|
@@ -75,6 +79,23 @@ apply `Foundation < Platform < Product` precedence to select a single winner. To
|
|
|
75
79
|
counts "tokens a platform ships" from `query` output should resolve first, or it will
|
|
76
80
|
double-count overridden tokens.
|
|
77
81
|
|
|
82
|
+
### Identity fields
|
|
83
|
+
|
|
84
|
+
`platform`, `platformVersion`, and `repository` are optional and have no effect on the
|
|
85
|
+
Foundation→Platform cascade — they exist so a manifest is self-describing wherever it
|
|
86
|
+
lives. This matters once a manifest is one of several configured in the same repo (via named
|
|
87
|
+
`[platforms.<id>]` profiles — see the SDK's `.design-data.toml` reference) or is fetched
|
|
88
|
+
from a remote repository: without `platform`, a manifest fetched by URL has no stable
|
|
89
|
+
identity of its own.
|
|
90
|
+
|
|
91
|
+
A single-platform repo with exactly one manifest **MAY** omit all three; the pattern
|
|
92
|
+
becomes worth adopting the moment a manifest is expected to move (incubating in a
|
|
93
|
+
monorepo ahead of a hand-off to its owning team) or coexist with siblings.
|
|
94
|
+
|
|
95
|
+
`platform`, when present, **SHOULD** match an id in the platform-implementations registry
|
|
96
|
+
(distinct from the token-level `platforms.json` registry, which enumerates *device
|
|
97
|
+
targets* like `desktop`/`mobile`, not *implementations* like `react-spectrum`).
|
|
98
|
+
|
|
78
99
|
### `extensions/` directory
|
|
79
100
|
|
|
80
101
|
**NORMATIVE:** Platform-local additions are declared as a sibling **directory** next to
|
|
@@ -92,6 +113,7 @@ extensions/
|
|
|
92
113
|
relationships/ <component>.json one CTR set per file
|
|
93
114
|
guidelines/ <topic>.json one guideline per file
|
|
94
115
|
platform-extensions/ <platform>-<registry>.json
|
|
116
|
+
implementations/ <component>.json one component's implementation rows
|
|
95
117
|
```
|
|
96
118
|
|
|
97
119
|
**NORMATIVE:** Each subdirectory is discovered by a recursive glob for `*.json` files (for
|
|
@@ -111,6 +133,9 @@ or empty subdirectory contributes nothing and is not an error.
|
|
|
111
133
|
injected into the corresponding catalog **add-or-replace by name** (for
|
|
112
134
|
`platform-extensions/`, by `termId`; see below). When two files declare the same name,
|
|
113
135
|
**the entry from the later file (in sorted path order) wins.**
|
|
136
|
+
* **`implementations/`** — one component's implementation rows per file, merged row-by-row into
|
|
137
|
+
that component's existing `implementations` array (never whole-array replaced). See
|
|
138
|
+
[`extensions/implementations/`](#extensionsimplementations) below.
|
|
114
139
|
|
|
115
140
|
**NORMATIVE:** Each fragment file **MUST** validate against its category's real JSON schema at
|
|
116
141
|
load time — this is enforced reference-SDK behavior, not an aspirational goal:
|
|
@@ -122,6 +147,8 @@ load time — this is enforced reference-SDK behavior, not an aspirational goal:
|
|
|
122
147
|
* **`relationships/`** → `relationship.schema.json` (see the Add/Override/remove rules above)
|
|
123
148
|
* **`platform-extensions/`** → `platform-extension.json` (see
|
|
124
149
|
[`extensions/platform-extensions/`](#extensionsplatform-extensions) below)
|
|
150
|
+
* **`implementations/`** → `implementation-mapping.schema.json` (see
|
|
151
|
+
[`extensions/implementations/`](#extensionsimplementations) below)
|
|
125
152
|
* **`tokens/`** → `cascade-file.schema.json` (see above)
|
|
126
153
|
|
|
127
154
|
A fragment that fails validation against its category schema is a manifest error — the
|
|
@@ -194,6 +221,51 @@ example, platform-specific state names). **NORMATIVE:** each file **MUST** valid
|
|
|
194
221
|
foundation registry — this mechanism annotates existing ids, it does **NOT** introduce new
|
|
195
222
|
ones.
|
|
196
223
|
|
|
224
|
+
#### `extensions/implementations/`
|
|
225
|
+
|
|
226
|
+
Platform-owned refinements of a component's
|
|
227
|
+
[`implementations`](component-format.md#implementations) — the packages, import paths, and
|
|
228
|
+
exported names a platform ships. Foundation component data carries canonical **default** rows;
|
|
229
|
+
a platform manifest refines only its own rows, so the implementation team that owns the
|
|
230
|
+
manifest also owns its mappings, and they travel with the manifest when it is ejected.
|
|
231
|
+
|
|
232
|
+
```json
|
|
233
|
+
{
|
|
234
|
+
"component": "button",
|
|
235
|
+
"implementations": [
|
|
236
|
+
{
|
|
237
|
+
"platform": "web",
|
|
238
|
+
"componentName": "Button",
|
|
239
|
+
"package": "@react-spectrum/s2"
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
"op": "remove",
|
|
243
|
+
"componentName": "Button",
|
|
244
|
+
"package": "@react-spectrum/button"
|
|
245
|
+
}
|
|
246
|
+
]
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
**NORMATIVE:** each file **MUST** validate against `implementation-mapping.schema.json`.
|
|
251
|
+
`component` **MUST** name a component in the catalog after `extensions/components/` has been
|
|
252
|
+
applied (so a fragment may target a platform-local component); an unknown component is a
|
|
253
|
+
manifest error. Entries apply in array order, files in sorted path order.
|
|
254
|
+
|
|
255
|
+
**NORMATIVE:** each entry has an *owner*: its own `implementation` field if present, otherwise
|
|
256
|
+
the manifest's top-level `platform` id. A manifest only matches rows its owner owns — rows
|
|
257
|
+
stamped with the same `implementation` id, or unstamped foundation defaults. Rows stamped with
|
|
258
|
+
a different `implementation` id are never modified or removed.
|
|
259
|
+
|
|
260
|
+
* **Upsert** (no `op`) — a full implementation row. When the entry omits `implementation` and
|
|
261
|
+
the manifest declares `platform`, the stored row is stamped with that id. The row replaces the
|
|
262
|
+
first existing row with the same `platform` and `componentName` that either carries the same
|
|
263
|
+
`implementation` id, or is an unstamped foundation default sharing a `package` or `importPath`
|
|
264
|
+
value. Otherwise it is appended.
|
|
265
|
+
* **Remove** (`"op": "remove"`) — a selector of `componentName` plus any of `platform`,
|
|
266
|
+
`implementation`, `package`, `importPath`. It deletes every owned row whose values equal every
|
|
267
|
+
selector field given. A remove that matches no owned row is a manifest error.
|
|
268
|
+
|
|
197
269
|
### `namingExceptions`
|
|
198
270
|
|
|
199
271
|
Platform-local overlay on the base naming-exceptions set used by naming validation.
|
|
@@ -216,6 +288,7 @@ A platform **MAY** declare formatting rules that control how structured name obj
|
|
|
216
288
|
| `casing` | string | One of: `kebab-case`, `camelCase`, `PascalCase`, `SCREAMING_SNAKE_CASE`. Default: `kebab-case`. |
|
|
217
289
|
| `delimiter` | string | Character(s) separating concepts in the serialized string (e.g. `-`, `_`, `.`, `/`). Default: `-`. |
|
|
218
290
|
| `abbreviations` | object | Map of full term → abbreviated form (e.g. `{ "background": "bg" }`). Abbreviations are applied after concept ordering and before casing. |
|
|
291
|
+
| `prefix` | string | Literal string prepended to the fully-formatted token name, applied after `casing`/`delimiter` and unaffected by either — for platform naming conventions that wrap the token name rather than reshape it (e.g. CSS custom properties like `--spectrum-`). |
|
|
219
292
|
|
|
220
293
|
**NORMATIVE:** When `formatting` is absent, the default serialization defined in [Taxonomy](taxonomy.md#default-serialization-legacy-format) is used.
|
|
221
294
|
|
package/spec/taxonomy.md
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
This document defines the **token taxonomy**: a hierarchical system of concept categories that classify design tokens, the **token term vocabulary** of allowed words within each category, and the **formatting style** rules that control serialization of structured token names into platform-consumable strings.
|
|
6
6
|
|
|
7
|
+
This chapter defines the Design Data-owned taxonomy contract. It intentionally does not restate platform-native naming semantics or external standards already owned elsewhere; when a platform or implementation standard defines those behaviors, this spec links to that authority instead of copying its normative rules.
|
|
8
|
+
|
|
7
9
|
## Motivation
|
|
8
10
|
|
|
9
11
|
"Naming convention" is too broad a term when discussing malleability across platform teams. A token name like `accent-background-color-hover` embeds multiple independent decisions:
|