@neuravision/construct 2.0.3 → 2.1.2

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.
Files changed (138) hide show
  1. package/CHANGELOG.md +318 -0
  2. package/README.md +158 -149
  3. package/behaviors/combobox.js +486 -0
  4. package/behaviors/drawer.js +18 -0
  5. package/behaviors/dropdown.js +310 -0
  6. package/behaviors/index.d.ts +335 -0
  7. package/behaviors/index.js +9 -0
  8. package/behaviors/internal/dialog-controller.js +421 -0
  9. package/behaviors/internal/dom.js +408 -0
  10. package/behaviors/internal/overlay.js +241 -0
  11. package/behaviors/internal/popup-layer.js +190 -0
  12. package/behaviors/modal.js +17 -0
  13. package/behaviors/popover.js +278 -0
  14. package/behaviors/select-menu.js +344 -0
  15. package/behaviors/tabs.js +241 -0
  16. package/behaviors/toggle-group.js +266 -0
  17. package/behaviors/tooltip.js +257 -0
  18. package/components/README.md +319 -83
  19. package/components/_shared.css +22 -10
  20. package/components/_shell-shared.css +20 -4
  21. package/components/accordion.css +8 -0
  22. package/components/app-shell-v2.css +28 -14
  23. package/components/app-shell.css +30 -14
  24. package/components/badge.css +15 -0
  25. package/components/banner.css +32 -1
  26. package/components/button.css +103 -15
  27. package/components/card.css +67 -8
  28. package/components/chart.css +26 -0
  29. package/components/checkbox.css +35 -2
  30. package/components/chip.css +30 -2
  31. package/components/combobox.css +21 -0
  32. package/components/datepicker.css +58 -9
  33. package/components/datum.css +277 -0
  34. package/components/dropdown.css +23 -3
  35. package/components/field.css +6 -4
  36. package/components/file-upload.css +1 -1
  37. package/components/index.css +5 -0
  38. package/components/list.css +28 -2
  39. package/components/meter.css +182 -0
  40. package/components/navbar.css +102 -4
  41. package/components/pagination.css +18 -0
  42. package/components/progress-bar.css +22 -1
  43. package/components/select-menu.css +8 -0
  44. package/components/select.css +8 -0
  45. package/components/sidebar.css +15 -2
  46. package/components/skip-link.css +6 -2
  47. package/components/slider.css +7 -1
  48. package/components/status.css +107 -0
  49. package/components/switch.css +66 -5
  50. package/components/table.css +53 -4
  51. package/components/tabs.css +55 -3
  52. package/components/toast.css +10 -1
  53. package/components/toggle-group.css +16 -5
  54. package/components/toolbar.css +17 -1
  55. package/components/tooltip.css +4 -0
  56. package/components/tree.css +30 -0
  57. package/docs/architecture.md +79 -0
  58. package/docs/behaviors.md +122 -0
  59. package/docs/fonts.md +70 -0
  60. package/docs/governance.md +85 -0
  61. package/docs/guidelines.md +72 -25
  62. package/examples/react/README.md +20 -0
  63. package/examples/react/SettingsModal.jsx +66 -0
  64. package/examples/react/construct.css +5 -0
  65. package/fonts.css +10 -0
  66. package/foundations.css +14 -1
  67. package/package.json +76 -21
  68. package/schemas/components.schema.json +122 -0
  69. package/schemas/examples/theme.example.json +27 -0
  70. package/schemas/primitives.schema.json +135 -0
  71. package/schemas/semantic.schema.json +224 -0
  72. package/schemas/theme.schema.json +63 -0
  73. package/scripts/build-tokens.mjs +1499 -0
  74. package/scripts/construct-theme.mjs +43 -0
  75. package/scripts/validate-tokens.mjs +25 -0
  76. package/standalone/accordion.css +3 -0
  77. package/standalone/alert.css +3 -0
  78. package/standalone/app-shell-v2.css +4 -0
  79. package/standalone/app-shell.css +4 -0
  80. package/standalone/avatar.css +3 -0
  81. package/standalone/badge.css +3 -0
  82. package/standalone/banner.css +3 -0
  83. package/standalone/breadcrumbs.css +3 -0
  84. package/standalone/button.css +3 -0
  85. package/standalone/card.css +3 -0
  86. package/standalone/chart.css +3 -0
  87. package/standalone/checkbox.css +3 -0
  88. package/standalone/chip.css +3 -0
  89. package/standalone/combobox.css +3 -0
  90. package/standalone/core.css +4 -0
  91. package/standalone/data-table.css +3 -0
  92. package/standalone/datepicker.css +3 -0
  93. package/standalone/datum.css +3 -0
  94. package/standalone/divider.css +3 -0
  95. package/standalone/drawer.css +3 -0
  96. package/standalone/dropdown.css +3 -0
  97. package/standalone/empty-state.css +3 -0
  98. package/standalone/field.css +3 -0
  99. package/standalone/file-upload.css +3 -0
  100. package/standalone/icon.css +3 -0
  101. package/standalone/input.css +3 -0
  102. package/standalone/list.css +3 -0
  103. package/standalone/meter.css +3 -0
  104. package/standalone/modal.css +3 -0
  105. package/standalone/navbar.css +3 -0
  106. package/standalone/pagination.css +3 -0
  107. package/standalone/popover.css +3 -0
  108. package/standalone/progress-bar.css +3 -0
  109. package/standalone/select-menu.css +3 -0
  110. package/standalone/select.css +3 -0
  111. package/standalone/sidebar.css +3 -0
  112. package/standalone/skeleton.css +3 -0
  113. package/standalone/skip-link.css +3 -0
  114. package/standalone/slider.css +3 -0
  115. package/standalone/spinner.css +3 -0
  116. package/standalone/status.css +3 -0
  117. package/standalone/switch.css +3 -0
  118. package/standalone/table.css +3 -0
  119. package/standalone/tabs.css +3 -0
  120. package/standalone/textarea.css +3 -0
  121. package/standalone/toast.css +3 -0
  122. package/standalone/toggle-group.css +3 -0
  123. package/standalone/toolbar.css +3 -0
  124. package/standalone/tooltip.css +3 -0
  125. package/standalone/tree.css +3 -0
  126. package/themes/README.md +37 -0
  127. package/themes/walnut.theme.json +106 -0
  128. package/tokens/README.md +135 -123
  129. package/tokens/components.json +64 -0
  130. package/tokens/primitives.json +268 -0
  131. package/tokens/semantic.dark.json +94 -0
  132. package/tokens/semantic.high-contrast-dark.json +94 -0
  133. package/tokens/semantic.high-contrast.json +94 -0
  134. package/tokens/semantic.light.json +179 -0
  135. package/tokens/tokens.css +960 -58
  136. package/tokens/tokens.js +729 -120
  137. package/tokens/tokens.json +1158 -116
  138. package/tokens/tokens.ts +729 -120
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neuravision/construct",
3
- "version": "2.0.3",
3
+ "version": "2.1.2",
4
4
  "description": "Construct Design System - Accessible, token-based design system for modern web applications",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -17,19 +17,59 @@
17
17
  "components"
18
18
  ],
19
19
  "type": "module",
20
+ "engines": {
21
+ "node": "^22.12.0 || >=24.0.0"
22
+ },
23
+ "sideEffects": [
24
+ "**/*.css"
25
+ ],
26
+ "bin": {
27
+ "construct-theme": "./scripts/construct-theme.mjs"
28
+ },
20
29
  "scripts": {
21
- "build": "node scripts/build-tokens.mjs",
22
- "check": "node scripts/build-tokens.mjs --check",
30
+ "build": "npm run build:tokens && npm run build:standalone",
31
+ "build:tokens": "node scripts/build-tokens.mjs",
32
+ "build:standalone": "node scripts/build-standalone-components.mjs",
33
+ "audit": "npm audit --audit-level=high",
34
+ "tokens:validate": "node scripts/validate-tokens.mjs",
35
+ "tokens:test": "node scripts/test-token-pipeline.mjs",
36
+ "themes:validate": "node scripts/construct-theme.mjs --theme themes/walnut.theme.json --validate-only",
37
+ "check": "npm run check:tokens && npm run check:standalone && npm run check:css && npm run check:exports && npm run check:version",
38
+ "check:tokens": "node scripts/build-tokens.mjs --check && npm run tokens:validate && npm run tokens:test && npm run themes:validate",
39
+ "check:standalone": "node scripts/build-standalone-components.mjs --check",
40
+ "check:css": "node scripts/validate-css-vars.mjs",
41
+ "check:exports": "node scripts/validate-package-exports.mjs",
42
+ "check:version": "node scripts/validate-version.mjs",
43
+ "test": "npm run test:behaviors && npm run test:storybook && npm run test:touch && npm run test:forced-colors",
44
+ "test:behaviors": "vitest --run --config behaviors/__tests__/vitest.config.js",
45
+ "test:storybook": "vitest --run",
46
+ "test:touch": "vitest --run --config vitest.touch.config.js",
47
+ "test:forced-colors": "vitest --run --config vitest.forced-colors.config.js",
23
48
  "storybook": "storybook dev -p 6006",
24
- "storybook:build": "storybook build"
49
+ "storybook:build": "storybook build",
50
+ "prepack": "npm run build && npm run check"
25
51
  },
26
52
  "exports": {
27
53
  "./foundations.css": "./foundations.css",
54
+ "./fonts.css": "./fonts.css",
28
55
  "./components/components.css": "./components/components.css",
29
56
  "./components/index.css": "./components/index.css",
30
- "./components/*.css": "./components/*.css",
57
+ "./components/core.css": "./standalone/core.css",
58
+ "./components/_keyframes.css": "./components/_keyframes.css",
59
+ "./components/_shared.css": "./components/_shared.css",
60
+ "./components/_shell-shared.css": "./components/_shell-shared.css",
61
+ "./components/*.css": "./standalone/*.css",
62
+ "./behaviors": {
63
+ "types": "./behaviors/index.d.ts",
64
+ "default": "./behaviors/index.js"
65
+ },
31
66
  "./tokens/tokens.css": "./tokens/tokens.css",
32
67
  "./tokens/tokens.json": "./tokens/tokens.json",
68
+ "./tokens/primitives.json": "./tokens/primitives.json",
69
+ "./tokens/semantic.light.json": "./tokens/semantic.light.json",
70
+ "./tokens/semantic.dark.json": "./tokens/semantic.dark.json",
71
+ "./tokens/semantic.high-contrast.json": "./tokens/semantic.high-contrast.json",
72
+ "./tokens/components.json": "./tokens/components.json",
33
73
  "./tokens/tokens": {
34
74
  "types": "./tokens/tokens.ts",
35
75
  "default": "./tokens/tokens.js"
@@ -37,31 +77,46 @@
37
77
  "./tokens": {
38
78
  "types": "./tokens/tokens.ts",
39
79
  "default": "./tokens/tokens.js"
40
- }
80
+ },
81
+ "./schemas/*.json": "./schemas/*.json",
82
+ "./schemas/examples/*.json": "./schemas/examples/*.json",
83
+ "./themes/*.json": "./themes/*.json"
41
84
  },
42
85
  "files": [
43
86
  "foundations.css",
44
- "tokens/tokens.css",
45
- "tokens/tokens.json",
46
- "tokens/tokens.js",
47
- "tokens/tokens.ts",
87
+ "fonts.css",
88
+ "tokens/*.css",
89
+ "tokens/*.json",
90
+ "tokens/*.js",
91
+ "tokens/*.ts",
48
92
  "tokens/README.md",
49
- "docs/guidelines.md",
93
+ "schemas/**/*.json",
94
+ "themes/*.json",
95
+ "themes/README.md",
50
96
  "components/*.css",
51
97
  "components/README.md",
98
+ "standalone/*.css",
99
+ "behaviors/*.js",
100
+ "behaviors/*.d.ts",
101
+ "behaviors/internal/*.js",
102
+ "scripts/build-tokens.mjs",
103
+ "scripts/construct-theme.mjs",
104
+ "scripts/validate-tokens.mjs",
105
+ "docs/*.md",
106
+ "examples/react/*",
107
+ "CHANGELOG.md",
52
108
  "README.md"
53
109
  ],
54
110
  "devDependencies": {
55
- "@storybook/addon-a11y": "^10.2.3",
56
- "@storybook/addon-docs": "^10.2.3",
57
- "@storybook/addon-themes": "^10.2.3",
58
- "@storybook/addon-vitest": "^10.2.3",
59
- "@storybook/html-vite": "^10.2.3",
60
- "@vitest/browser-playwright": "^4.0.18",
61
- "@vitest/coverage-v8": "^4.0.18",
62
- "playwright": "^1.58.1",
111
+ "@storybook/addon-a11y": "^10.5.0",
112
+ "@storybook/addon-docs": "^10.5.0",
113
+ "@storybook/addon-themes": "^10.5.0",
114
+ "@storybook/addon-vitest": "^10.5.0",
115
+ "@storybook/html-vite": "^10.5.0",
116
+ "@vitest/browser-playwright": "^4.1.10",
117
+ "playwright": "^1.61.1",
63
118
  "remark-gfm": "^4.0.1",
64
- "storybook": "^10.2.3",
65
- "vitest": "^4.0.18"
119
+ "storybook": "^10.5.0",
120
+ "vitest": "^4.1.10"
66
121
  }
67
122
  }
@@ -0,0 +1,122 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://neuravision.dev/construct/schemas/components.schema.json",
4
+ "title": "Construct component token contract",
5
+ "type": "object",
6
+ "required": ["button", "control", "card", "status", "metric", "meter", "datum"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "button": {
10
+ "type": "object",
11
+ "additionalProperties": false,
12
+ "required": ["background", "backgroundHover", "backgroundActive", "border", "color", "height", "paddingX", "fontSize", "lineHeight", "fontWeight", "radius", "gap", "loadingSpinnerSize"],
13
+ "properties": {
14
+ "background": { "$ref": "#/$defs/token" },
15
+ "backgroundHover": { "$ref": "#/$defs/token" },
16
+ "backgroundActive": { "$ref": "#/$defs/token" },
17
+ "border": { "$ref": "#/$defs/token" },
18
+ "color": { "$ref": "#/$defs/token" },
19
+ "height": { "$ref": "#/$defs/token" },
20
+ "paddingX": { "$ref": "#/$defs/token" },
21
+ "fontSize": { "$ref": "#/$defs/token" },
22
+ "lineHeight": { "$ref": "#/$defs/token" },
23
+ "fontWeight": { "$ref": "#/$defs/token" },
24
+ "radius": { "$ref": "#/$defs/token" },
25
+ "gap": { "$ref": "#/$defs/token" },
26
+ "loadingSpinnerSize": { "$ref": "#/$defs/token" }
27
+ }
28
+ },
29
+ "control": {
30
+ "type": "object",
31
+ "additionalProperties": false,
32
+ "required": ["background", "backgroundHover", "backgroundDisabled", "border", "borderHover", "borderFocus", "text", "placeholder", "radius"],
33
+ "properties": {
34
+ "background": { "$ref": "#/$defs/token" },
35
+ "backgroundHover": { "$ref": "#/$defs/token" },
36
+ "backgroundDisabled": { "$ref": "#/$defs/token" },
37
+ "border": { "$ref": "#/$defs/token" },
38
+ "borderHover": { "$ref": "#/$defs/token" },
39
+ "borderFocus": { "$ref": "#/$defs/token" },
40
+ "text": { "$ref": "#/$defs/token" },
41
+ "placeholder": { "$ref": "#/$defs/token" },
42
+ "radius": { "$ref": "#/$defs/token" }
43
+ }
44
+ },
45
+ "card": {
46
+ "type": "object",
47
+ "additionalProperties": false,
48
+ "required": ["background", "border", "radius", "padding", "shadow", "shadowHover"],
49
+ "properties": {
50
+ "background": { "$ref": "#/$defs/token" },
51
+ "border": { "$ref": "#/$defs/token" },
52
+ "radius": { "$ref": "#/$defs/token" },
53
+ "padding": { "$ref": "#/$defs/token" },
54
+ "shadow": { "$ref": "#/$defs/token" },
55
+ "shadowHover": { "$ref": "#/$defs/token" }
56
+ }
57
+ },
58
+ "status": {
59
+ "type": "object",
60
+ "additionalProperties": false,
61
+ "required": ["gap", "fontSize", "iconSize"],
62
+ "properties": {
63
+ "gap": { "$ref": "#/$defs/token" },
64
+ "fontSize": { "$ref": "#/$defs/token" },
65
+ "iconSize": { "$ref": "#/$defs/token" }
66
+ }
67
+ },
68
+ "metric": {
69
+ "type": "object",
70
+ "additionalProperties": false,
71
+ "required": ["background", "border", "radius", "padding", "valueFontSize", "labelFontSize"],
72
+ "properties": {
73
+ "background": { "$ref": "#/$defs/token" },
74
+ "border": { "$ref": "#/$defs/token" },
75
+ "radius": { "$ref": "#/$defs/token" },
76
+ "padding": { "$ref": "#/$defs/token" },
77
+ "valueFontSize": { "$ref": "#/$defs/token" },
78
+ "labelFontSize": { "$ref": "#/$defs/token" }
79
+ }
80
+ },
81
+ "meter": {
82
+ "type": "object",
83
+ "additionalProperties": false,
84
+ "required": ["height", "radius", "track"],
85
+ "properties": {
86
+ "height": { "$ref": "#/$defs/token" },
87
+ "radius": { "$ref": "#/$defs/token" },
88
+ "track": { "$ref": "#/$defs/token" }
89
+ }
90
+ },
91
+ "datum": {
92
+ "type": "object",
93
+ "additionalProperties": false,
94
+ "required": ["edgeWidth", "tickWidth", "tickHeight", "originLength", "markSize", "scaleHeight", "scaleMinorStep", "scaleMajorStep"],
95
+ "properties": {
96
+ "edgeWidth": { "$ref": "#/$defs/token" },
97
+ "tickWidth": { "$ref": "#/$defs/token" },
98
+ "tickHeight": { "$ref": "#/$defs/token" },
99
+ "originLength": { "$ref": "#/$defs/token" },
100
+ "markSize": { "$ref": "#/$defs/token" },
101
+ "scaleHeight": { "$ref": "#/$defs/token" },
102
+ "scaleMinorStep": { "$ref": "#/$defs/token" },
103
+ "scaleMajorStep": { "$ref": "#/$defs/token" }
104
+ }
105
+ }
106
+ },
107
+ "$defs": {
108
+ "token": {
109
+ "anyOf": [
110
+ {
111
+ "type": "string",
112
+ "pattern": "^\\{[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)+\\}$"
113
+ },
114
+ {
115
+ "type": "string",
116
+ "minLength": 1,
117
+ "pattern": "^(?!.*(?:/\\*|\\*/|[;{}]|!\\s*important|\\b(?:url|var)\\s*\\())[^\\u0000-\\u001F\\u007F]+$"
118
+ }
119
+ ]
120
+ }
121
+ }
122
+ }
@@ -0,0 +1,27 @@
1
+ {
2
+ "$schema": "../theme.schema.json",
3
+ "name": "example-theme",
4
+ "extends": "light",
5
+ "semantic": {
6
+ "color": {
7
+ "brand": {
8
+ "primary": "{color.ocean.700}",
9
+ "primaryHover": "{color.ocean.800}",
10
+ "primaryActive": "{color.ocean.900}"
11
+ }
12
+ }
13
+ },
14
+ "components": {
15
+ "button": {
16
+ "radius": "{radius.pill}"
17
+ }
18
+ },
19
+ "contrast": [
20
+ {
21
+ "name": "button label",
22
+ "foreground": "components.button.color",
23
+ "background": "components.button.background",
24
+ "minRatio": 4.5
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,135 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://neuravision.dev/construct/schemas/primitives.schema.json",
4
+ "title": "Construct primitive tokens",
5
+ "type": "object",
6
+ "required": [
7
+ "color",
8
+ "font",
9
+ "space",
10
+ "radius",
11
+ "border",
12
+ "opacity",
13
+ "size",
14
+ "layout",
15
+ "shadow",
16
+ "motion",
17
+ "zIndex",
18
+ "breakpoint"
19
+ ],
20
+ "additionalProperties": false,
21
+ "properties": {
22
+ "color": {
23
+ "type": "object",
24
+ "minProperties": 1,
25
+ "additionalProperties": {
26
+ "type": "object",
27
+ "minProperties": 1,
28
+ "patternProperties": {
29
+ "^(0|[1-9][0-9]*)$": { "$ref": "#/$defs/color" }
30
+ },
31
+ "additionalProperties": false
32
+ }
33
+ },
34
+ "font": {
35
+ "type": "object",
36
+ "required": ["family", "weight", "size", "lineHeight", "letterSpacing"],
37
+ "additionalProperties": false,
38
+ "properties": {
39
+ "family": {
40
+ "type": "object",
41
+ "required": ["brand", "text", "mono"],
42
+ "additionalProperties": { "type": "string", "minLength": 1 }
43
+ },
44
+ "weight": { "$ref": "#/$defs/numberScale" },
45
+ "size": { "$ref": "#/$defs/nonNegativeScale" },
46
+ "lineHeight": { "$ref": "#/$defs/nonNegativeScale" },
47
+ "letterSpacing": { "$ref": "#/$defs/numberScale" }
48
+ }
49
+ },
50
+ "space": { "$ref": "#/$defs/nonNegativeScale" },
51
+ "radius": { "$ref": "#/$defs/nonNegativeScale" },
52
+ "border": {
53
+ "type": "object",
54
+ "required": ["width"],
55
+ "additionalProperties": false,
56
+ "properties": {
57
+ "width": { "$ref": "#/$defs/nonNegativeScale" }
58
+ }
59
+ },
60
+ "opacity": {
61
+ "type": "object",
62
+ "minProperties": 1,
63
+ "additionalProperties": {
64
+ "type": "number",
65
+ "minimum": 0,
66
+ "maximum": 1
67
+ }
68
+ },
69
+ "size": {
70
+ "type": "object",
71
+ "required": ["controlHeight", "icon"],
72
+ "additionalProperties": false,
73
+ "properties": {
74
+ "controlHeight": { "$ref": "#/$defs/nonNegativeScale" },
75
+ "icon": { "$ref": "#/$defs/nonNegativeScale" }
76
+ }
77
+ },
78
+ "layout": {
79
+ "type": "object",
80
+ "required": ["container", "gutter", "gridGap", "navbar"],
81
+ "additionalProperties": false,
82
+ "properties": {
83
+ "container": { "$ref": "#/$defs/nonNegativeScale" },
84
+ "gutter": { "$ref": "#/$defs/nonNegativeScale" },
85
+ "gridGap": { "$ref": "#/$defs/nonNegativeScale" },
86
+ "navbar": { "$ref": "#/$defs/nonNegativeScale" }
87
+ }
88
+ },
89
+ "shadow": {
90
+ "type": "object",
91
+ "minProperties": 1,
92
+ "additionalProperties": { "type": "string", "minLength": 1 }
93
+ },
94
+ "motion": {
95
+ "type": "object",
96
+ "required": ["duration", "easing"],
97
+ "additionalProperties": false,
98
+ "properties": {
99
+ "duration": { "$ref": "#/$defs/nonNegativeScale" },
100
+ "easing": {
101
+ "type": "object",
102
+ "minProperties": 1,
103
+ "additionalProperties": { "type": "string", "minLength": 1 }
104
+ }
105
+ }
106
+ },
107
+ "zIndex": { "$ref": "#/$defs/numberScale" },
108
+ "breakpoint": { "$ref": "#/$defs/nonNegativeScale" }
109
+ },
110
+ "$defs": {
111
+ "color": {
112
+ "type": "string",
113
+ "pattern": "^#(?:[0-9a-fA-F]{3}|[0-9a-fA-F]{4}|[0-9a-fA-F]{6}|[0-9a-fA-F]{8})$"
114
+ },
115
+ "numberScale": {
116
+ "type": "object",
117
+ "minProperties": 1,
118
+ "patternProperties": {
119
+ "^[A-Za-z0-9][A-Za-z0-9_-]*$": { "type": "number" }
120
+ },
121
+ "additionalProperties": false
122
+ },
123
+ "nonNegativeScale": {
124
+ "type": "object",
125
+ "minProperties": 1,
126
+ "patternProperties": {
127
+ "^[A-Za-z0-9][A-Za-z0-9_-]*$": {
128
+ "type": "number",
129
+ "minimum": 0
130
+ }
131
+ },
132
+ "additionalProperties": false
133
+ }
134
+ }
135
+ }
@@ -0,0 +1,224 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://neuravision.dev/construct/schemas/semantic.schema.json",
4
+ "title": "Construct semantic token contract",
5
+ "type": "object",
6
+ "required": ["color", "theme", "font", "typography", "radius", "shadow"],
7
+ "additionalProperties": false,
8
+ "properties": {
9
+ "color": {
10
+ "type": "object",
11
+ "required": [
12
+ "brand",
13
+ "text",
14
+ "background",
15
+ "border",
16
+ "state",
17
+ "stateSurface",
18
+ "stateBorder",
19
+ "stateText",
20
+ "overlay",
21
+ "focus",
22
+ "avatarSeed",
23
+ "chartSeries"
24
+ ],
25
+ "additionalProperties": false,
26
+ "properties": {
27
+ "brand": {
28
+ "type": "object",
29
+ "additionalProperties": false,
30
+ "required": ["primary", "primaryHover", "primaryActive", "accent", "accentHover", "accentActive", "accentStrong", "onAccent"],
31
+ "properties": {
32
+ "primary": { "$ref": "#/$defs/token" },
33
+ "primaryHover": { "$ref": "#/$defs/token" },
34
+ "primaryActive": { "$ref": "#/$defs/token" },
35
+ "accent": { "$ref": "#/$defs/token" },
36
+ "accentHover": { "$ref": "#/$defs/token" },
37
+ "accentActive": { "$ref": "#/$defs/token" },
38
+ "accentStrong": { "$ref": "#/$defs/token" },
39
+ "onAccent": { "$ref": "#/$defs/token" }
40
+ }
41
+ },
42
+ "text": {
43
+ "type": "object",
44
+ "additionalProperties": false,
45
+ "required": ["primary", "secondary", "muted", "inverse", "onPrimary"],
46
+ "properties": {
47
+ "primary": { "$ref": "#/$defs/token" },
48
+ "secondary": { "$ref": "#/$defs/token" },
49
+ "muted": { "$ref": "#/$defs/token" },
50
+ "inverse": { "$ref": "#/$defs/token" },
51
+ "onPrimary": { "$ref": "#/$defs/token" }
52
+ }
53
+ },
54
+ "background": {
55
+ "type": "object",
56
+ "additionalProperties": false,
57
+ "required": ["canvas", "surface", "elevated", "muted", "subtle"],
58
+ "properties": {
59
+ "canvas": { "$ref": "#/$defs/token" },
60
+ "surface": { "$ref": "#/$defs/token" },
61
+ "elevated": { "$ref": "#/$defs/token" },
62
+ "muted": { "$ref": "#/$defs/token" },
63
+ "subtle": { "$ref": "#/$defs/token" }
64
+ }
65
+ },
66
+ "border": {
67
+ "type": "object",
68
+ "additionalProperties": false,
69
+ "required": ["subtle", "default", "strong", "muted"],
70
+ "properties": {
71
+ "subtle": { "$ref": "#/$defs/token" },
72
+ "default": { "$ref": "#/$defs/token" },
73
+ "strong": { "$ref": "#/$defs/token" },
74
+ "muted": { "$ref": "#/$defs/token" }
75
+ }
76
+ },
77
+ "state": { "$ref": "#/$defs/stateGroupWithSolid" },
78
+ "stateSurface": { "$ref": "#/$defs/stateGroup" },
79
+ "stateBorder": { "$ref": "#/$defs/stateGroup" },
80
+ "stateText": { "$ref": "#/$defs/stateGroup" },
81
+ "overlay": {
82
+ "type": "object",
83
+ "additionalProperties": false,
84
+ "required": ["scrim"],
85
+ "properties": { "scrim": { "$ref": "#/$defs/token" } }
86
+ },
87
+ "focus": {
88
+ "type": "object",
89
+ "additionalProperties": false,
90
+ "required": ["ring"],
91
+ "properties": { "ring": { "$ref": "#/$defs/token" } }
92
+ },
93
+ "avatarSeed": {
94
+ "type": "object",
95
+ "minProperties": 16,
96
+ "patternProperties": {
97
+ "^[1-8](Bg|Fg)$": { "$ref": "#/$defs/token" }
98
+ },
99
+ "additionalProperties": false
100
+ },
101
+ "chartSeries": {
102
+ "type": "object",
103
+ "minProperties": 8,
104
+ "patternProperties": {
105
+ "^[1-8]$": { "$ref": "#/$defs/token" }
106
+ },
107
+ "additionalProperties": false
108
+ }
109
+ }
110
+ },
111
+ "theme": {
112
+ "type": "object",
113
+ "required": ["colorScheme"],
114
+ "additionalProperties": false,
115
+ "properties": {
116
+ "colorScheme": { "enum": ["light", "dark", "light dark", "dark light"] }
117
+ }
118
+ },
119
+ "font": {
120
+ "type": "object",
121
+ "required": ["family"],
122
+ "additionalProperties": false,
123
+ "properties": {
124
+ "family": {
125
+ "type": "object",
126
+ "additionalProperties": false,
127
+ "required": ["heading", "body", "code"],
128
+ "properties": {
129
+ "heading": { "$ref": "#/$defs/token" },
130
+ "body": { "$ref": "#/$defs/token" },
131
+ "code": { "$ref": "#/$defs/token" }
132
+ }
133
+ }
134
+ }
135
+ },
136
+ "typography": {
137
+ "type": "object",
138
+ "required": ["display", "h1", "h2", "h3", "h4", "body", "bodySm", "label", "caption"],
139
+ "additionalProperties": false,
140
+ "properties": {
141
+ "display": { "$ref": "#/$defs/typeStyle" },
142
+ "h1": { "$ref": "#/$defs/typeStyle" },
143
+ "h2": { "$ref": "#/$defs/typeStyle" },
144
+ "h3": { "$ref": "#/$defs/typeStyle" },
145
+ "h4": { "$ref": "#/$defs/typeStyle" },
146
+ "body": { "$ref": "#/$defs/typeStyle" },
147
+ "bodySm": { "$ref": "#/$defs/typeStyle" },
148
+ "label": { "$ref": "#/$defs/typeStyle" },
149
+ "caption": { "$ref": "#/$defs/typeStyle" }
150
+ }
151
+ },
152
+ "radius": {
153
+ "type": "object",
154
+ "additionalProperties": false,
155
+ "required": ["control", "card", "modal", "pill"],
156
+ "properties": {
157
+ "control": { "$ref": "#/$defs/token" },
158
+ "card": { "$ref": "#/$defs/token" },
159
+ "modal": { "$ref": "#/$defs/token" },
160
+ "pill": { "$ref": "#/$defs/token" }
161
+ }
162
+ },
163
+ "shadow": {
164
+ "type": "object",
165
+ "additionalProperties": false,
166
+ "required": ["card", "dropdown", "modal"],
167
+ "properties": {
168
+ "card": { "$ref": "#/$defs/token" },
169
+ "dropdown": { "$ref": "#/$defs/token" },
170
+ "modal": { "$ref": "#/$defs/token" }
171
+ }
172
+ }
173
+ },
174
+ "$defs": {
175
+ "token": {
176
+ "anyOf": [
177
+ {
178
+ "type": "string",
179
+ "pattern": "^\\{[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)+\\}$"
180
+ },
181
+ {
182
+ "type": "string",
183
+ "minLength": 1,
184
+ "pattern": "^(?!.*(?:/\\*|\\*/|[;{}]|!\\s*important|\\b(?:url|var)\\s*\\())[^\\u0000-\\u001F\\u007F]+$"
185
+ }
186
+ ]
187
+ },
188
+ "stateGroup": {
189
+ "type": "object",
190
+ "required": ["info", "success", "warning", "danger"],
191
+ "additionalProperties": false,
192
+ "properties": {
193
+ "info": { "$ref": "#/$defs/token" },
194
+ "success": { "$ref": "#/$defs/token" },
195
+ "warning": { "$ref": "#/$defs/token" },
196
+ "danger": { "$ref": "#/$defs/token" }
197
+ }
198
+ },
199
+ "stateGroupWithSolid": {
200
+ "type": "object",
201
+ "required": ["info", "success", "warning", "danger", "onSolid"],
202
+ "additionalProperties": false,
203
+ "properties": {
204
+ "info": { "$ref": "#/$defs/token" },
205
+ "success": { "$ref": "#/$defs/token" },
206
+ "warning": { "$ref": "#/$defs/token" },
207
+ "danger": { "$ref": "#/$defs/token" },
208
+ "onSolid": { "$ref": "#/$defs/token" }
209
+ }
210
+ },
211
+ "typeStyle": {
212
+ "type": "object",
213
+ "required": ["fontFamily", "fontSize", "lineHeight", "fontWeight", "letterSpacing"],
214
+ "additionalProperties": false,
215
+ "properties": {
216
+ "fontFamily": { "$ref": "#/$defs/token" },
217
+ "fontSize": { "$ref": "#/$defs/token" },
218
+ "lineHeight": { "$ref": "#/$defs/token" },
219
+ "fontWeight": { "$ref": "#/$defs/token" },
220
+ "letterSpacing": { "$ref": "#/$defs/token" }
221
+ }
222
+ }
223
+ }
224
+ }