@nan0web/ui 1.12.2 → 3.1.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/README.md +18 -355
- package/package.json +36 -22
- package/src/Component/index.js +1 -5
- package/src/Model/Element.js +183 -0
- package/src/Model/index.js +2 -2
- package/src/Theme/AppTheme.js +19 -0
- package/src/Theme/CustomTheme.js +32 -0
- package/src/Theme/DarkLightTheme.js +34 -0
- package/src/Theme/Theme.js +25 -0
- package/src/Theme/atoms/Avatar.js +20 -0
- package/src/Theme/atoms/Badge.js +28 -0
- package/src/Theme/atoms/Button.js +88 -0
- package/src/Theme/atoms/Checkbox.js +26 -0
- package/src/Theme/atoms/Input.js +28 -0
- package/src/Theme/atoms/Radio.js +26 -0
- package/src/Theme/atoms/Select.js +16 -0
- package/src/Theme/atoms/TextArea.js +17 -0
- package/src/Theme/atoms/Typography.js +26 -0
- package/src/Theme/atoms/index.js +11 -0
- package/src/Theme/createTheme.js +22 -0
- package/src/Theme/index.js +20 -0
- package/src/Theme/molecules/Card.js +24 -0
- package/src/Theme/molecules/index.js +3 -0
- package/src/Theme/organisms/Modal.js +24 -0
- package/src/Theme/organisms/index.js +3 -0
- package/src/Theme/presets/HighContrastTheme.js +65 -0
- package/src/Theme/presets/NightTheme.js +66 -0
- package/src/Theme/presets/index.js +4 -0
- package/src/Theme/tokens.js +115 -0
- package/src/core/InputAdapter.js +1 -2
- package/src/core/Intent.js +22 -8
- package/src/core/Message/Message.js +3 -0
- package/src/core/OutputAdapter.js +9 -13
- package/src/core/index.js +7 -4
- package/src/core/resolvePositionalArgs.js +51 -0
- package/src/domain/Content.js +5 -5
- package/src/domain/Document.js +1 -1
- package/src/domain/HeroModel.js +1 -1
- package/src/domain/ModelAsApp.js +310 -20
- package/src/domain/ModelAsApp.story.js +117 -0
- package/src/domain/app/GalleryCommand.js +9 -8
- package/src/domain/app/{GalleryRenderIntent.js → GalleryRenderCommand.js} +20 -20
- package/src/domain/app/IntentAuditor.js +53 -0
- package/src/domain/app/JsIntentAuditor.js +145 -0
- package/src/domain/app/PyIntentAuditor.js +144 -0
- package/src/domain/app/SnapshotAuditor.js +82 -86
- package/src/domain/app/SnapshotRunner.js +1 -1
- package/src/domain/app/UIApp.js +12 -21
- package/src/domain/components/ShellModel.js +2 -2
- package/src/index.js +38 -10
- package/src/inspect.js +4 -0
- package/src/testing/SnapshotRunner.js +2 -1
- package/src/utils/format.js +21 -0
- package/src/utils/processI18n.js +27 -0
- package/src/utils/resolveContext.js +79 -0
- package/types/Component/index.d.ts +1 -5
- package/types/Model/Element.d.ts +87 -0
- package/types/Model/index.d.ts +2 -2
- package/types/Theme/AppTheme.d.ts +14 -0
- package/types/Theme/CustomTheme.d.ts +21 -0
- package/types/Theme/DarkLightTheme.d.ts +16 -0
- package/types/Theme/Theme.d.ts +18 -0
- package/types/Theme/atoms/Avatar.d.ts +14 -0
- package/types/Theme/atoms/Badge.d.ts +22 -0
- package/types/Theme/atoms/Button.d.ts +144 -0
- package/types/Theme/atoms/Checkbox.d.ts +20 -0
- package/types/Theme/atoms/Input.d.ts +22 -0
- package/types/Theme/atoms/Radio.d.ts +20 -0
- package/types/Theme/atoms/Select.d.ts +15 -0
- package/types/Theme/atoms/TextArea.d.ts +17 -0
- package/types/Theme/atoms/Typography.d.ts +47 -0
- package/types/Theme/atoms/index.d.ts +10 -0
- package/types/Theme/createTheme.d.ts +7 -0
- package/types/Theme/index.d.ts +10 -0
- package/types/Theme/molecules/Card.d.ts +18 -0
- package/types/Theme/molecules/index.d.ts +2 -0
- package/types/Theme/organisms/Modal.d.ts +18 -0
- package/types/Theme/organisms/index.d.ts +2 -0
- package/types/Theme/presets/HighContrastTheme.d.ts +2 -0
- package/types/Theme/presets/NightTheme.d.ts +2 -0
- package/types/Theme/presets/index.d.ts +3 -0
- package/types/Theme/tokens.d.ts +119 -0
- package/types/core/Intent.d.ts +10 -7
- package/types/core/Message/Message.d.ts +3 -0
- package/types/core/OutputAdapter.d.ts +2 -4
- package/types/core/index.d.ts +5 -2
- package/types/core/resolvePositionalArgs.d.ts +24 -0
- package/types/docs/README.md.d.ts +1 -0
- package/types/domain/Content.d.ts +2 -2
- package/types/domain/Document.d.ts +4 -3
- package/types/domain/FooterModel.d.ts +2 -1
- package/types/domain/HeroModel.d.ts +2 -2
- package/types/domain/ModelAsApp.d.ts +49 -5
- package/types/domain/ModelAsApp.story.d.ts +1 -0
- package/types/domain/app/GalleryCommand.d.ts +6 -37
- package/types/domain/app/GalleryRenderCommand.d.ts +27 -0
- package/types/domain/app/IntentAuditor.d.ts +23 -0
- package/types/domain/app/JsIntentAuditor.d.ts +22 -0
- package/types/domain/app/PyIntentAuditor.d.ts +22 -0
- package/types/domain/app/SnapshotAuditor.d.ts +34 -25
- package/types/domain/app/SnapshotRunner.d.ts +2 -2
- package/types/domain/app/UIApp.d.ts +14 -11
- package/types/domain/components/ShellModel.d.ts +1 -5
- package/types/index.d.ts +10 -10
- package/types/inspect.d.ts +4 -0
- package/types/testing/verifySnapshot.d.ts +1 -1
- package/types/utils/format.d.ts +5 -0
- package/types/utils/processI18n.d.ts +8 -0
- package/types/utils/resolveContext.d.ts +21 -0
- package/src/App/Command/DepsCommand.js +0 -24
- package/src/App/Core/CoreApp.js +0 -125
- package/src/App/Core/UI.js +0 -63
- package/src/App/Core/Widget.js +0 -61
- package/src/App/Core/index.js +0 -11
- package/src/App/Scenario.js +0 -45
- package/src/App/User/Command/Message.js +0 -3
- package/src/App/User/Command/index.js +0 -5
- package/src/App/User/UserApp.js +0 -85
- package/src/App/User/UserUI.js +0 -20
- package/src/App/User/index.js +0 -9
- package/src/App/index.js +0 -14
- package/src/Component/Process/Input.js +0 -63
- package/src/Component/Process/Process.js +0 -24
- package/src/Component/Process/index.js +0 -5
- package/src/Component/Welcome/Input.js +0 -48
- package/src/Component/Welcome/Welcome.js +0 -22
- package/src/Component/Welcome/index.js +0 -5
- package/src/Frame/Frame.js +0 -608
- package/src/Frame/Props.js +0 -96
- package/src/StdIn.js +0 -100
- package/src/StdOut.js +0 -95
- package/src/View/RenderOptions.js +0 -48
- package/src/View/View.js +0 -306
- package/src/core/Message/index.js +0 -6
- package/types/App/Command/DepsCommand.d.ts +0 -14
- package/types/App/Core/CoreApp.d.ts +0 -70
- package/types/App/Core/UI.d.ts +0 -38
- package/types/App/Core/Widget.d.ts +0 -39
- package/types/App/Core/index.d.ts +0 -10
- package/types/App/Scenario.d.ts +0 -26
- package/types/App/User/Command/Message.d.ts +0 -2
- package/types/App/User/Command/index.d.ts +0 -3
- package/types/App/User/UserApp.d.ts +0 -41
- package/types/App/User/UserUI.d.ts +0 -9
- package/types/App/User/index.d.ts +0 -8
- package/types/App/index.d.ts +0 -12
- package/types/Component/Process/Input.d.ts +0 -48
- package/types/Component/Process/Process.d.ts +0 -13
- package/types/Component/Process/index.d.ts +0 -4
- package/types/Component/Welcome/Input.d.ts +0 -34
- package/types/Component/Welcome/Welcome.d.ts +0 -13
- package/types/Component/Welcome/index.d.ts +0 -4
- package/types/Frame/Frame.d.ts +0 -186
- package/types/Frame/Props.d.ts +0 -77
- package/types/StdIn.d.ts +0 -62
- package/types/StdOut.d.ts +0 -52
- package/types/View/RenderOptions.d.ts +0 -29
- package/types/View/View.d.ts +0 -124
- package/types/core/Message/index.d.ts +0 -4
- package/types/domain/app/GalleryRenderIntent.d.ts +0 -31
|
@@ -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
|
+
}
|
package/src/Model/index.js
CHANGED
|
@@ -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 }
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { merge } from '@nan0web/types'
|
|
2
|
+
import Theme from './Theme.js'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Creates a theme instance with merged configuration.
|
|
6
|
+
*
|
|
7
|
+
* @param {Partial<import('./Theme.js').ThemeConfig>} overrides
|
|
8
|
+
* @returns {import('./Theme.js').ThemeConfig}
|
|
9
|
+
*/
|
|
10
|
+
export function createTheme(overrides = {}) {
|
|
11
|
+
/**
|
|
12
|
+
* This function uses merge from @nan0web/types to create a new theme.
|
|
13
|
+
* It ensures nested theme properties like atoms, molecules, organisms are deeply merged.
|
|
14
|
+
*/
|
|
15
|
+
const base = {
|
|
16
|
+
atoms: { ...Theme.atoms },
|
|
17
|
+
molecules: { ...Theme.molecules },
|
|
18
|
+
organisms: { ...Theme.organisms },
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
return merge(base, overrides)
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import Theme from './Theme.js'
|
|
2
|
+
import CustomTheme, { getUserTheme } from './CustomTheme.js'
|
|
3
|
+
import AppTheme from './AppTheme.js'
|
|
4
|
+
import DarkLightTheme from './DarkLightTheme.js'
|
|
5
|
+
import HighContrastTheme from './presets/HighContrastTheme.js'
|
|
6
|
+
import NightTheme from './presets/NightTheme.js'
|
|
7
|
+
import { createTheme } from './createTheme.js'
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
Theme,
|
|
11
|
+
CustomTheme,
|
|
12
|
+
getUserTheme,
|
|
13
|
+
AppTheme,
|
|
14
|
+
DarkLightTheme,
|
|
15
|
+
HighContrastTheme,
|
|
16
|
+
NightTheme,
|
|
17
|
+
createTheme,
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export default Theme
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { tokens } from '../tokens.js'
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Theme definition for Card molecule.
|
|
5
|
+
*
|
|
6
|
+
* @typedef {Object} CardTheme
|
|
7
|
+
* @property {string} borderRadius
|
|
8
|
+
* @property {string} boxShadow
|
|
9
|
+
* @property {string} padding
|
|
10
|
+
* @property {string} backgroundColor
|
|
11
|
+
* @property {string} borderColor
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Card molecule theme.
|
|
16
|
+
* @type {CardTheme}
|
|
17
|
+
*/
|
|
18
|
+
export default {
|
|
19
|
+
borderRadius: tokens.radius.lg,
|
|
20
|
+
boxShadow: tokens.shadow.md,
|
|
21
|
+
padding: tokens.space.lg,
|
|
22
|
+
backgroundColor: tokens.color.background,
|
|
23
|
+
borderColor: tokens.border.color.muted,
|
|
24
|
+
}
|