@nan0web/ui 1.12.3 → 3.1.1

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 (136) hide show
  1. package/package.json +29 -20
  2. package/src/Component/index.js +1 -5
  3. package/src/Model/Element.js +183 -0
  4. package/src/Theme/AppTheme.js +19 -0
  5. package/src/Theme/CustomTheme.js +32 -0
  6. package/src/Theme/DarkLightTheme.js +34 -0
  7. package/src/Theme/Theme.js +25 -0
  8. package/src/Theme/atoms/Avatar.js +20 -0
  9. package/src/Theme/atoms/Badge.js +28 -0
  10. package/src/Theme/atoms/Button.js +88 -0
  11. package/src/Theme/atoms/Checkbox.js +26 -0
  12. package/src/Theme/atoms/Input.js +28 -0
  13. package/src/Theme/atoms/Radio.js +26 -0
  14. package/src/Theme/atoms/Select.js +16 -0
  15. package/src/Theme/atoms/TextArea.js +17 -0
  16. package/src/Theme/atoms/Typography.js +26 -0
  17. package/src/Theme/atoms/index.js +11 -0
  18. package/src/Theme/createTheme.js +22 -0
  19. package/src/Theme/index.js +20 -0
  20. package/src/Theme/molecules/Card.js +24 -0
  21. package/src/Theme/molecules/index.js +3 -0
  22. package/src/Theme/organisms/Modal.js +24 -0
  23. package/src/Theme/organisms/index.js +3 -0
  24. package/src/Theme/presets/HighContrastTheme.js +65 -0
  25. package/src/Theme/presets/NightTheme.js +66 -0
  26. package/src/Theme/presets/index.js +4 -0
  27. package/src/Theme/tokens.js +115 -0
  28. package/src/core/InputAdapter.js +1 -2
  29. package/src/core/Intent.js +22 -8
  30. package/src/core/Message/Message.js +3 -0
  31. package/src/core/OutputAdapter.js +9 -13
  32. package/src/core/index.js +7 -4
  33. package/src/domain/ModelAsApp.js +1 -1
  34. package/src/domain/app/IntentAuditor.js +53 -0
  35. package/src/domain/app/JsIntentAuditor.js +145 -0
  36. package/src/domain/app/PyIntentAuditor.js +144 -0
  37. package/src/domain/app/SnapshotAuditor.js +8 -8
  38. package/src/domain/components/ShellModel.js +2 -2
  39. package/src/index.js +35 -9
  40. package/src/inspect.js +3 -0
  41. package/src/utils/format.js +21 -0
  42. package/src/utils/processI18n.js +27 -0
  43. package/src/utils/resolveContext.js +79 -0
  44. package/types/Component/index.d.ts +1 -5
  45. package/types/Model/Element.d.ts +87 -0
  46. package/types/Theme/AppTheme.d.ts +14 -0
  47. package/types/Theme/CustomTheme.d.ts +21 -0
  48. package/types/Theme/DarkLightTheme.d.ts +16 -0
  49. package/types/Theme/Theme.d.ts +18 -0
  50. package/types/Theme/atoms/Avatar.d.ts +14 -0
  51. package/types/Theme/atoms/Badge.d.ts +22 -0
  52. package/types/Theme/atoms/Button.d.ts +144 -0
  53. package/types/Theme/atoms/Checkbox.d.ts +20 -0
  54. package/types/Theme/atoms/Input.d.ts +22 -0
  55. package/types/Theme/atoms/Radio.d.ts +20 -0
  56. package/types/Theme/atoms/Select.d.ts +15 -0
  57. package/types/Theme/atoms/TextArea.d.ts +17 -0
  58. package/types/Theme/atoms/Typography.d.ts +47 -0
  59. package/types/Theme/atoms/index.d.ts +10 -0
  60. package/types/Theme/createTheme.d.ts +7 -0
  61. package/types/Theme/index.d.ts +10 -0
  62. package/types/Theme/molecules/Card.d.ts +18 -0
  63. package/types/Theme/molecules/index.d.ts +2 -0
  64. package/types/Theme/organisms/Modal.d.ts +18 -0
  65. package/types/Theme/organisms/index.d.ts +2 -0
  66. package/types/Theme/presets/HighContrastTheme.d.ts +2 -0
  67. package/types/Theme/presets/NightTheme.d.ts +2 -0
  68. package/types/Theme/presets/index.d.ts +3 -0
  69. package/types/Theme/tokens.d.ts +119 -0
  70. package/types/core/Intent.d.ts +10 -7
  71. package/types/core/Message/Message.d.ts +3 -0
  72. package/types/core/OutputAdapter.d.ts +2 -4
  73. package/types/core/index.d.ts +5 -2
  74. package/types/domain/Document.d.ts +2 -1
  75. package/types/domain/FooterModel.d.ts +2 -1
  76. package/types/domain/ModelAsApp.d.ts +48 -48
  77. package/types/domain/app/IntentAuditor.d.ts +23 -0
  78. package/types/domain/app/JsIntentAuditor.d.ts +22 -0
  79. package/types/domain/app/PyIntentAuditor.d.ts +22 -0
  80. package/types/domain/app/SnapshotAuditor.d.ts +5 -6
  81. package/types/domain/components/ShellModel.d.ts +1 -5
  82. package/types/index.d.ts +7 -9
  83. package/types/inspect.d.ts +3 -0
  84. package/types/utils/format.d.ts +5 -0
  85. package/types/utils/processI18n.d.ts +8 -0
  86. package/types/utils/resolveContext.d.ts +21 -0
  87. package/src/App/Command/DepsCommand.js +0 -24
  88. package/src/App/Core/CoreApp.js +0 -125
  89. package/src/App/Core/UI.js +0 -63
  90. package/src/App/Core/Widget.js +0 -61
  91. package/src/App/Core/index.js +0 -11
  92. package/src/App/Scenario.js +0 -45
  93. package/src/App/User/Command/Message.js +0 -3
  94. package/src/App/User/Command/index.js +0 -5
  95. package/src/App/User/UserApp.js +0 -85
  96. package/src/App/User/UserUI.js +0 -20
  97. package/src/App/User/index.js +0 -9
  98. package/src/App/index.js +0 -14
  99. package/src/Component/Process/Input.js +0 -63
  100. package/src/Component/Process/Process.js +0 -24
  101. package/src/Component/Process/index.js +0 -5
  102. package/src/Component/Welcome/Input.js +0 -48
  103. package/src/Component/Welcome/Welcome.js +0 -22
  104. package/src/Component/Welcome/index.js +0 -5
  105. package/src/Frame/Frame.js +0 -608
  106. package/src/Frame/Props.js +0 -96
  107. package/src/StdIn.js +0 -100
  108. package/src/StdOut.js +0 -95
  109. package/src/View/RenderOptions.js +0 -48
  110. package/src/View/View.js +0 -306
  111. package/src/core/Message/index.js +0 -6
  112. package/types/App/Command/DepsCommand.d.ts +0 -14
  113. package/types/App/Core/CoreApp.d.ts +0 -70
  114. package/types/App/Core/UI.d.ts +0 -38
  115. package/types/App/Core/Widget.d.ts +0 -39
  116. package/types/App/Core/index.d.ts +0 -10
  117. package/types/App/Scenario.d.ts +0 -26
  118. package/types/App/User/Command/Message.d.ts +0 -2
  119. package/types/App/User/Command/index.d.ts +0 -3
  120. package/types/App/User/UserApp.d.ts +0 -41
  121. package/types/App/User/UserUI.d.ts +0 -9
  122. package/types/App/User/index.d.ts +0 -8
  123. package/types/App/index.d.ts +0 -12
  124. package/types/Component/Process/Input.d.ts +0 -48
  125. package/types/Component/Process/Process.d.ts +0 -13
  126. package/types/Component/Process/index.d.ts +0 -4
  127. package/types/Component/Welcome/Input.d.ts +0 -34
  128. package/types/Component/Welcome/Welcome.d.ts +0 -13
  129. package/types/Component/Welcome/index.d.ts +0 -4
  130. package/types/Frame/Frame.d.ts +0 -186
  131. package/types/Frame/Props.d.ts +0 -77
  132. package/types/StdIn.d.ts +0 -62
  133. package/types/StdOut.d.ts +0 -52
  134. package/types/View/RenderOptions.d.ts +0 -29
  135. package/types/View/View.d.ts +0 -124
  136. package/types/core/Message/index.d.ts +0 -4
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nan0web/ui",
3
- "version": "1.12.3",
3
+ "version": "3.1.1",
4
4
  "description": "NaN•Web UI. One application logic (algorithm) and many UI.",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
@@ -56,11 +56,20 @@
56
56
  "nan0web": {
57
57
  "workflowDir": "docs/{locale}/workflows",
58
58
  "workflows": [
59
- "olm-ui-architecture.md",
60
- "olm-ui-architecture-core.md",
61
- "olm-ui-architecture-adapters.md",
59
+ "architecture.md",
62
60
  "forge-component.md",
63
- "interface-welding.md"
61
+ "interface-welding.md",
62
+ "nan0web-v2-roadmap.md",
63
+ "nan0web.md",
64
+ "olm-ui-architecture-adapters.md",
65
+ "olm-ui-architecture-core.md",
66
+ "olm-ui-architecture-i18n.md",
67
+ "olm-ui-architecture-testing.md",
68
+ "olm-ui-architecture.md",
69
+ "pipeline-no4-adapter.md",
70
+ "pipeline-no7-ui-web.md",
71
+ "pipeline-no8-ui-mobile.md",
72
+ "ui-update.md"
64
73
  ],
65
74
  "inspectors": [
66
75
  "./src/domain/app/SnapshotAuditor.js"
@@ -79,23 +88,23 @@
79
88
  "lit": "^3.3.2",
80
89
  "vite": "^6.4.1",
81
90
  "vitest": "^3.2.4",
82
- "@nan0web/db-fs": "1.2.2",
83
- "@nan0web/event": "1.0.1",
84
- "@nan0web/i18n": "1.5.0",
85
- "@nan0web/icons": "1.1.0",
86
- "@nan0web/inspect": "1.0.0",
87
- "@nan0web/test": "1.1.4",
88
- "@nan0web/ui-cli": "2.14.0",
89
- "@nan0web/release": "1.0.3",
90
- "@nan0web/nan0web.app": "0.1.0",
91
- "@nan0web/ui-lit": "1.1.0"
91
+ "@nan0web/db-fs": "3.1.0",
92
+ "@nan0web/inspect": "3.1.0",
93
+ "@nan0web/ui-cli": "3.1.1",
94
+ "@nan0web/i18n": "3.1.1",
95
+ "@nan0web/icons": "3.1.0",
96
+ "@nan0web/release": "3.1.1",
97
+ "@nan0web/test": "3.1.0",
98
+ "@nan0web/ui-lit": "3.1.0",
99
+ "@nan0web/nan0web.app": "3.1.0"
92
100
  },
93
101
  "dependencies": {
94
102
  "string-width": "^7.2.0",
95
- "@nan0web/co": "2.0.1",
96
- "@nan0web/core": "1.1.3",
97
- "@nan0web/log": "1.1.1",
98
- "@nan0web/types": "1.7.6"
103
+ "@nan0web/co": "3.1.0",
104
+ "@nan0web/event": "3.1.0",
105
+ "@nan0web/log": "3.1.0",
106
+ "@nan0web/types": "3.1.0",
107
+ "@nan0web/core": "3.1.0"
99
108
  },
100
109
  "scripts": {
101
110
  "prebuild": "rm -rf types/",
@@ -113,7 +122,7 @@
113
122
  "test:play": "node --test --test-timeout=3333 \"play/**/*.test.js\"",
114
123
  "test:snapshots": "node src/testing/GalleryGenerator.js",
115
124
  "test:gallery": "npm run test:snapshots && npx nan0gallery --dir=snapshots/core",
116
- "test:audit": "nan0cli audit --dir snapshots/core --data .",
125
+ "test:audit": "nan0cli snapshots --dir snapshots/core --data .",
117
126
  "test:stories": "node --test \"src/**/*.story.js\"",
118
127
  "test:all": "npm run test && npm run test:docs && npm run test:play && npm run test:stories && npm run knip",
119
128
  "knip": "knip --production",
@@ -1,11 +1,7 @@
1
- import Welcome from './Welcome/index.js'
2
- import Process from './Process/index.js'
3
1
  import SortableList from './SortableList/index.js'
4
2
 
5
- export { Welcome, Process, SortableList }
3
+ export { SortableList }
6
4
 
7
5
  export default {
8
- Welcome,
9
- Process,
10
6
  SortableList,
11
7
  }
@@ -0,0 +1,183 @@
1
+ /**
2
+ * @file Element — the model of a declarative UI block.
3
+ * Format: { Button: [...], $variant: 'info', $onClick: fn }
4
+ * Framework-agnostic.
5
+ */
6
+
7
+ export default class Element {
8
+ /** @type {Record<string, string | ((val: any, key: string) => Record<string, any>)>} */
9
+ static PROP_ALIASES = {
10
+ $class: 'className',
11
+ $for: 'htmlFor',
12
+ $aria: (val, key) => ({
13
+ [key
14
+ .slice(1)
15
+ .replace(/([A-Z])/g, '-$1')
16
+ .toLowerCase()]: val,
17
+ }), // $ariaLabel → aria-label
18
+ $on: (val, key) => ({ [key.slice(1).toLowerCase()]: val }), // $onClick → onclick
19
+ }
20
+
21
+ /**
22
+ * The component type or HTML tag (e.g., "Button", "div")
23
+ * @type {string}
24
+ */
25
+ type
26
+
27
+ /**
28
+ * The content of the element.
29
+ * Can be:
30
+ * - string → text
31
+ * - true → empty
32
+ * - array → nested blocks { Icon } or text nodes
33
+ * @type {string | true | any[]}
34
+ */
35
+ content
36
+
37
+ /**
38
+ * Props extracted from $-keys.
39
+ * For example, { $onClick: fn, $variant: 'info' } → { onClick: fn, variant: 'info' }
40
+ * @type {Object}
41
+ */
42
+ props
43
+
44
+ /**
45
+ * Creates an `Element` from a declarative block.
46
+ * @param {Object} input - For example, { Button: ["Click"], $variant: "primary" }
47
+ */
48
+ constructor(input = {}) {
49
+ const tags = Element.extractTags(input)
50
+ const [type, content] = tags[0] || ['div', '']
51
+ this.type = type
52
+ this.content = content === true ? [] : content
53
+ this.props = Element.extractProps(input, true, Element.parseProp.bind(Element))
54
+ }
55
+
56
+ /**
57
+ * Checks if the element contains nested elements (not only text).
58
+ * @returns {boolean}
59
+ */
60
+ hasChildren() {
61
+ return (
62
+ Array.isArray(this.content) &&
63
+ this.content.some((c) => typeof c === 'object' && !Array.isArray(c))
64
+ )
65
+ }
66
+
67
+ /**
68
+ * Checks if the content contains text fragments.
69
+ * @returns {boolean}
70
+ */
71
+ hasText() {
72
+ return (
73
+ typeof this.content === 'string' ||
74
+ (Array.isArray(this.content) && this.content.some((c) => typeof c === 'string'))
75
+ )
76
+ }
77
+
78
+ /**
79
+ * Returns an array of child elements (Element instances).
80
+ * @returns {Element[]}
81
+ */
82
+ getChildElements() {
83
+ if (!this.hasChildren()) return []
84
+ return /** @type {any[]} */ (this.content)
85
+ .filter((item) => typeof item === 'object' && item && !Array.isArray(item))
86
+ .map((item) => Element.from(item))
87
+ }
88
+
89
+ /**
90
+ * Factory method to create or return an existing `Element`.
91
+ * @param {Object} input
92
+ * @returns {Element}
93
+ */
94
+ static from(input) {
95
+ if (input instanceof Element) return input
96
+ return new Element(input)
97
+ }
98
+
99
+ /**
100
+ * Parses $-props.
101
+ * Converts for example:
102
+ * - $style="color:red;font-size:14px" → { style: { color: 'red', 'font-size': '14px' } }
103
+ * - $onClick=fn → { onClick: fn }
104
+ * - $ariaHidden=true → { 'aria-hidden': true }
105
+ *
106
+ * @param {string} key - The name of the prop
107
+ * @param {any} value - The value of the prop
108
+ * @returns {Object} - An object { propName: newVal }
109
+ */
110
+ static parseProp(key, value) {
111
+ if (key === '$style' && typeof value === 'string') {
112
+ return { style: this.parseInlineStyle(value) }
113
+ }
114
+
115
+ if (key.startsWith('$aria') && key.length > 5) {
116
+ const ariaKey = key
117
+ .slice(5)
118
+ .replace(/([A-Z])/g, '$1')
119
+ .toLowerCase()
120
+ return { [`aria-${ariaKey}`]: value }
121
+ }
122
+
123
+ if (key.startsWith('$on') && key.length > 3) {
124
+ return { [key.slice(1)]: value }
125
+ }
126
+
127
+ const propAlias = this.PROP_ALIASES[key]
128
+ if (typeof propAlias === 'string') {
129
+ return { [propAlias]: value }
130
+ }
131
+
132
+ if (typeof propAlias === 'function') {
133
+ return propAlias(value, key)
134
+ }
135
+
136
+ if (key.startsWith('$')) {
137
+ return { [key.slice(1)]: value }
138
+ }
139
+
140
+ return { [key]: value }
141
+ }
142
+
143
+ /**
144
+ * Parses an inline CSS style string.
145
+ * @param {string} styleStr
146
+ * @returns {Object}
147
+ */
148
+ static parseInlineStyle(styleStr) {
149
+ return styleStr.split(';').reduce((style, rule) => {
150
+ const [key, val] = rule.trim().split(':')
151
+ if (key && val) style[key.trim()] = val.trim()
152
+ return style
153
+ }, {})
154
+ }
155
+
156
+ /**
157
+ * Extracts $-props from the block.
158
+ * @param {Object} block
159
+ * @param {boolean} keep$ - Whether to keep the prefix `$`.
160
+ * @param {Function} [flatMap] - Function that transforms a key-value pair into a new key-value pair.
161
+ * @returns {Object}
162
+ */
163
+ static extractProps(block, keep$ = false, flatMap = undefined) {
164
+ const entries = Object.entries(block)
165
+ .filter(([k]) => k.startsWith('$'))
166
+ .map(([k, v]) => [keep$ ? k : k.slice(1), v])
167
+
168
+ if (typeof flatMap === 'function') {
169
+ return Object.fromEntries(entries.flatMap(([k, v]) => Object.entries(flatMap(k, v))))
170
+ }
171
+
172
+ return Object.fromEntries(entries)
173
+ }
174
+
175
+ /**
176
+ * Extracts tags (non-prefixed keys) from the block.
177
+ * @param {Object} block
178
+ * @returns {Array<[string, any]>}
179
+ */
180
+ static extractTags(block) {
181
+ return Object.entries(block).filter(([k]) => !k.startsWith('$'))
182
+ }
183
+ }
@@ -0,0 +1,19 @@
1
+ import Theme from './Theme.js'
2
+
3
+ /**
4
+ * Base application theme.
5
+ * Should be extended by app-specific themes.
6
+ *
7
+ * @typedef {import("./Theme.js").ThemeConfig & { fontFamily?: string }} AppThemeConfig
8
+ */
9
+
10
+ /**
11
+ * Base application theme.
12
+ * Should be extended by app-specific themes.
13
+ *
14
+ * @type {AppThemeConfig}
15
+ */
16
+ export default {
17
+ ...Theme,
18
+ fontFamily: 'system-ui',
19
+ }
@@ -0,0 +1,32 @@
1
+ import Theme from './Theme.js'
2
+ import { createTheme } from './createTheme.js'
3
+ import * as presets from './presets/index.js'
4
+
5
+ /**
6
+ * @typedef {{ atoms?: object, molecules?: object, organisms?: object }} UserThemeConfig
7
+ */
8
+
9
+ /**
10
+ * Returns selected or custom user theme.
11
+ * @param {string | UserThemeConfig} themeNameOrConfig
12
+ * @returns {import('./Theme.js').ThemeConfig}
13
+ */
14
+ export function getUserTheme(themeNameOrConfig) {
15
+ if (typeof themeNameOrConfig === 'string') {
16
+ const preset = presets[themeNameOrConfig]
17
+ if (preset) return preset
18
+ throw new Error(`Theme preset "${themeNameOrConfig}" not found.`)
19
+ }
20
+
21
+ return createTheme(themeNameOrConfig)
22
+ }
23
+
24
+ /**
25
+ * Custom user theme.
26
+ * Extends the base Theme to allow passing configuration during instantiation.
27
+ * @param {UserThemeConfig} config
28
+ * @returns {import('./Theme.js').ThemeConfig}
29
+ */
30
+ export default function CustomTheme(config) {
31
+ return createTheme(config)
32
+ }
@@ -0,0 +1,34 @@
1
+ import { createTheme } from './createTheme.js'
2
+
3
+ /**
4
+ * Theme that automatically switches between light/dark modes.
5
+ */
6
+ export default class DarkLightTheme {
7
+ /** @type {Object} */
8
+ static light = {
9
+ background: '#fff',
10
+ text: '#000',
11
+ }
12
+
13
+ /** @type {Object} */
14
+ static dark = {
15
+ background: '#000',
16
+ text: '#fff',
17
+ }
18
+
19
+ /** @type {string} */
20
+ static current = 'auto' // "light", "dark", or "auto"
21
+
22
+ /**
23
+ * Gets active theme (light, dark, or system preference).
24
+ * @returns {Object}
25
+ */
26
+ static getActiveTheme() {
27
+ if (this.current === 'light') return this.light
28
+ if (this.current === 'dark') return this.dark
29
+
30
+ // @ts-ignore
31
+ const isDark = globalThis.matchMedia?.('(prefers-color-scheme: dark)')?.matches
32
+ return isDark ? this.dark : this.light
33
+ }
34
+ }
@@ -0,0 +1,25 @@
1
+ import * as atoms from './atoms/index.js'
2
+ import * as molecules from './molecules/index.js'
3
+ import * as organisms from './organisms/index.js'
4
+
5
+ /**
6
+ * Universal UI theme foundation.
7
+ * Holds atoms, molecules, and organisms styling configs.
8
+ *
9
+ * @typedef {Object} ThemeConfig
10
+ * @property {Partial<typeof atoms>} atoms
11
+ * @property {typeof molecules} molecules
12
+ * @property {typeof organisms} organisms
13
+ */
14
+
15
+ /**
16
+ * Universal UI theme foundation.
17
+ * Contains styling configurations for all component types.
18
+ *
19
+ * @type {ThemeConfig}
20
+ */
21
+ export default {
22
+ atoms,
23
+ molecules,
24
+ organisms,
25
+ }
@@ -0,0 +1,20 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Avatar atom.
5
+ *
6
+ * @typedef {Object} AvatarTheme
7
+ * @property {string} size
8
+ * @property {string} borderRadius
9
+ * @property {string} border
10
+ */
11
+
12
+ /**
13
+ * Avatar atom theme.
14
+ * @type {AvatarTheme}
15
+ */
16
+ export default {
17
+ size: '2.5rem',
18
+ borderRadius: tokens.radius.full,
19
+ border: `${tokens.border.width.sm} solid ${tokens.border.color.default}`,
20
+ }
@@ -0,0 +1,28 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Badge atom.
5
+ *
6
+ * @typedef {Object} BadgeTheme
7
+ * @property {string} borderRadius
8
+ * @property {string} fontSize
9
+ * @property {string} paddingX
10
+ * @property {string} paddingY
11
+ * @property {string} fontWeight
12
+ * @property {string} backgroundColor
13
+ * @property {string} color
14
+ */
15
+
16
+ /**
17
+ * Badge atom theme.
18
+ * @type {BadgeTheme}
19
+ */
20
+ export default {
21
+ borderRadius: tokens.radius.full,
22
+ fontSize: tokens.font.size.sm,
23
+ paddingX: tokens.space.sm,
24
+ paddingY: tokens.space.xs,
25
+ fontWeight: tokens.font.weight.bold,
26
+ backgroundColor: tokens.color.primary,
27
+ color: tokens.color.text,
28
+ }
@@ -0,0 +1,88 @@
1
+ import Input from './Input.js'
2
+ import { tokens } from '../tokens.js'
3
+
4
+ /**
5
+ * Theme definition for Button atom.
6
+ * Inherits common properties from Input and defines colour and shadow.
7
+ *
8
+ * @typedef {Object} ButtonTheme
9
+ * @property {string} color
10
+ * @property {string} background
11
+ * @property {string} shadow
12
+ * @property {string} hoverBackground
13
+ * @property {Object} solid
14
+ * @property {Object} outline
15
+ * @property {Object} size
16
+ * @property {Object} animation
17
+ * @property {string} borderColor
18
+ * @property {string} borderRadius
19
+ * @property {string} borderWidth
20
+ * @property {string} fontSize
21
+ * @property {string} paddingX
22
+ * @property {string} paddingY
23
+ * @property {string} fontFamily
24
+ */
25
+
26
+ /**
27
+ * Button atom theme.
28
+ * @type {ButtonTheme}
29
+ */
30
+ export default {
31
+ ...Input,
32
+ color: tokens.color.text,
33
+ background: tokens.color.primary,
34
+ shadow: tokens.shadow.sm,
35
+ hoverBackground: 'color-mix(in srgb, var(--color-primary) 80%, black)',
36
+
37
+ solid: {
38
+ primary: { background: '#0d6efd', color: '#fff', border: '#0d6efd' },
39
+ secondary: { background: '#6c757d', color: '#fff', border: '#6c757d' },
40
+ success: { background: '#198754', color: '#fff', border: '#198754' },
41
+ warning: { background: '#ffc107', color: '#212529', border: '#ffc107' },
42
+ danger: { background: '#dc3545', color: '#fff', border: '#dc3545' },
43
+ info: { background: '#0dcaf0', color: '#fff', border: '#0dcaf0' },
44
+ light: { background: '#f8f9fa', color: '#212529', border: '#f8f9fa' },
45
+ dark: { background: '#212529', color: '#fff', border: '#212529' },
46
+ link: { background: 'transparent', color: '#0d6efd', border: 'transparent' },
47
+ },
48
+
49
+ outline: {
50
+ primary: { background: 'transparent', color: '#0d6efd', border: '#0d6efd' },
51
+ secondary: { background: 'transparent', color: '#6c757d', border: '#6c757d' },
52
+ success: { background: 'transparent', color: '#198754', border: '#198754' },
53
+ warning: { background: 'transparent', color: '#ffc107', border: '#ffc107' },
54
+ danger: { background: 'transparent', color: '#dc3545', border: '#dc3545' },
55
+ info: { background: 'transparent', color: '#0dcaf0', border: '#0dcaf0' },
56
+ light: { background: 'transparent', color: '#212529', border: '#212529' },
57
+ dark: { background: 'transparent', color: '#212529', border: '#212529' },
58
+ },
59
+
60
+ size: {
61
+ sm: {
62
+ fontSize: '0.875rem',
63
+ paddingX: '0.5rem',
64
+ paddingY: '0.25rem',
65
+ },
66
+ md: {
67
+ fontSize: '1rem',
68
+ paddingX: '1rem',
69
+ paddingY: '0.5rem',
70
+ },
71
+ },
72
+
73
+ animation: {
74
+ transition: 'background 0.15s ease, transform 0.1s ease',
75
+ hoverAdjust: 20,
76
+ activeAdjust: -30,
77
+ focusScale: 1.02,
78
+ activeScale: 0.98,
79
+ disabledOpacity: 0.65,
80
+ },
81
+
82
+ borderColor: tokens.border.color.default,
83
+ borderRadius: tokens.radius.md,
84
+ borderWidth: tokens.border.width.md,
85
+ fontSize: tokens.font.size.base,
86
+ paddingX: tokens.space.lg,
87
+ paddingY: tokens.space.md,
88
+ }
@@ -0,0 +1,26 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Checkbox atom.
5
+ *
6
+ * @typedef {Object} CheckboxTheme
7
+ * @property {string} size
8
+ * @property {string} borderColor
9
+ * @property {string} borderRadius
10
+ * @property {string} borderWidth
11
+ * @property {string} backgroundColor
12
+ * @property {string} checkedColor
13
+ */
14
+
15
+ /**
16
+ * Checkbox atom theme.
17
+ * @type {CheckboxTheme}
18
+ */
19
+ export default {
20
+ size: '1.25rem',
21
+ borderColor: tokens.border.color.default,
22
+ borderRadius: tokens.radius.sm,
23
+ borderWidth: tokens.border.width.sm,
24
+ backgroundColor: tokens.color.background,
25
+ checkedColor: tokens.color.primary,
26
+ }
@@ -0,0 +1,28 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Input atom.
5
+ *
6
+ * @typedef {Object} InputTheme
7
+ * @property {string} borderRadius
8
+ * @property {string} borderWidth
9
+ * @property {string} borderColor
10
+ * @property {string} fontSize
11
+ * @property {string} paddingX
12
+ * @property {string} paddingY
13
+ * @property {string} fontFamily
14
+ */
15
+
16
+ /**
17
+ * Input atom theme.
18
+ * @type {InputTheme}
19
+ */
20
+ export default {
21
+ borderRadius: tokens.radius.md,
22
+ borderWidth: tokens.border.width.md,
23
+ borderColor: tokens.border.color.default,
24
+ fontSize: tokens.font.size.base,
25
+ paddingX: tokens.space.lg,
26
+ paddingY: tokens.space.md,
27
+ fontFamily: tokens.font.family,
28
+ }
@@ -0,0 +1,26 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Radio atom.
5
+ *
6
+ * @typedef {Object} RadioTheme
7
+ * @property {string} size
8
+ * @property {string} borderColor
9
+ * @property {string} borderRadius
10
+ * @property {string} borderWidth
11
+ * @property {string} backgroundColor
12
+ * @property {string} checkedColor
13
+ */
14
+
15
+ /**
16
+ * Radio atom theme.
17
+ * @type {RadioTheme}
18
+ */
19
+ export default {
20
+ size: '1.25rem',
21
+ borderColor: tokens.border.color.default,
22
+ borderRadius: tokens.radius.full,
23
+ borderWidth: tokens.border.width.sm,
24
+ backgroundColor: tokens.color.background,
25
+ checkedColor: tokens.color.primary,
26
+ }
@@ -0,0 +1,16 @@
1
+ import Input from './Input.js'
2
+
3
+ /**
4
+ * Theme definition for Select atom.
5
+ * Inherits all properties from InputTheme.
6
+ *
7
+ * @typedef {import("./Input.js").InputTheme} SelectTheme
8
+ */
9
+
10
+ /**
11
+ * Select atom theme.
12
+ * @type {SelectTheme}
13
+ */
14
+ export default {
15
+ ...Input,
16
+ }
@@ -0,0 +1,17 @@
1
+ import Input from './Input.js'
2
+
3
+ /**
4
+ * Theme definition for TextArea atom.
5
+ *
6
+ * @typedef {Object} TextAreaTheme
7
+ * @property {string} height
8
+ */
9
+
10
+ /**
11
+ * TextArea atom theme.
12
+ * @type {TextAreaTheme & import("./Input.js").InputTheme}
13
+ */
14
+ export default {
15
+ ...Input,
16
+ height: '6rem',
17
+ }
@@ -0,0 +1,26 @@
1
+ import { tokens } from '../tokens.js'
2
+
3
+ /**
4
+ * Theme definition for Typography atom.
5
+ *
6
+ * @typedef {Object} TypographyTheme
7
+ * @property {Object} variants
8
+ */
9
+
10
+ /**
11
+ * Typography atom theme.
12
+ * @type {TypographyTheme}
13
+ */
14
+ export default {
15
+ variants: {
16
+ h1: { fontSize: '2rem', fontWeight: tokens.font.weight.bold },
17
+ h2: { fontSize: '1.75rem', fontWeight: tokens.font.weight.bold },
18
+ h3: { fontSize: '1.5rem', fontWeight: tokens.font.weight.medium },
19
+ h4: { fontSize: '1.25rem', fontWeight: tokens.font.weight.medium },
20
+ h5: { fontSize: '1.125rem', fontWeight: tokens.font.weight.normal },
21
+ h6: { fontSize: '1rem', fontWeight: tokens.font.weight.normal },
22
+ body: { fontSize: tokens.font.size.base, fontWeight: tokens.font.weight.normal },
23
+ small: { fontSize: tokens.font.size.sm, fontWeight: tokens.font.weight.normal },
24
+ caption: { fontSize: tokens.font.size.xs, fontWeight: tokens.font.weight.normal },
25
+ },
26
+ }
@@ -0,0 +1,11 @@
1
+ import Avatar from './Avatar.js'
2
+ import Badge from './Badge.js'
3
+ import Button from './Button.js'
4
+ import Checkbox from './Checkbox.js'
5
+ import Input from './Input.js'
6
+ import Radio from './Radio.js'
7
+ import Select from './Select.js'
8
+ import TextArea from './TextArea.js'
9
+ import Typography from './Typography.js'
10
+
11
+ export { Avatar, Badge, Button, Checkbox, Input, Radio, Select, TextArea, Typography }