@haiyue/ui 0.1.1 → 0.2.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 (99) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +504 -1
  3. package/dist/adapters/web/controls.d.ts +19 -0
  4. package/dist/adapters/web/controls.js +284 -0
  5. package/dist/adapters/web/dom.d.ts +10 -0
  6. package/dist/adapters/web/dom.js +98 -0
  7. package/dist/adapters/web/index.d.ts +3 -0
  8. package/dist/adapters/web/index.js +3 -0
  9. package/dist/adapters/web/renderer.d.ts +18 -0
  10. package/dist/adapters/web/renderer.js +545 -0
  11. package/dist/adapters/web/styles.d.ts +3 -0
  12. package/dist/adapters/web/styles.js +62 -0
  13. package/dist/adapters/web/types.d.ts +46 -0
  14. package/dist/adapters/web/types.js +2 -0
  15. package/dist/affix.d.ts +35 -0
  16. package/dist/affix.js +137 -0
  17. package/dist/badge.d.ts +45 -0
  18. package/dist/badge.js +168 -0
  19. package/dist/border-beam.js +3 -1
  20. package/dist/breadcrumb.d.ts +37 -0
  21. package/dist/breadcrumb.js +210 -0
  22. package/dist/button-group.d.ts +12 -0
  23. package/dist/button-group.js +72 -0
  24. package/dist/button.d.ts +15 -1
  25. package/dist/button.js +101 -12
  26. package/dist/cascader.d.ts +65 -0
  27. package/dist/cascader.js +479 -0
  28. package/dist/collapse.d.ts +55 -0
  29. package/dist/collapse.js +261 -0
  30. package/dist/core/actions.d.ts +32 -0
  31. package/dist/core/actions.js +145 -0
  32. package/dist/core/data.d.ts +4 -0
  33. package/dist/core/data.js +27 -0
  34. package/dist/core/index.d.ts +7 -0
  35. package/dist/core/index.js +6 -0
  36. package/dist/core/platform-view.d.ts +17 -0
  37. package/dist/core/platform-view.js +84 -0
  38. package/dist/core/selection.d.ts +14 -0
  39. package/dist/core/selection.js +93 -0
  40. package/dist/core/text.d.ts +31 -0
  41. package/dist/core/text.js +154 -0
  42. package/dist/core/types.d.ts +250 -0
  43. package/dist/core/types.js +2 -0
  44. package/dist/core/validation.d.ts +24 -0
  45. package/dist/core/validation.js +238 -0
  46. package/dist/date-picker.d.ts +60 -0
  47. package/dist/date-picker.js +355 -0
  48. package/dist/dialog.d.ts +4 -0
  49. package/dist/dialog.js +23 -5
  50. package/dist/divider.d.ts +33 -0
  51. package/dist/divider.js +113 -0
  52. package/dist/draggable.d.ts +78 -0
  53. package/dist/draggable.js +255 -0
  54. package/dist/expandable.d.ts +32 -0
  55. package/dist/expandable.js +136 -0
  56. package/dist/index.d.ts +47 -1
  57. package/dist/index.js +69 -0
  58. package/dist/input.d.ts +30 -1
  59. package/dist/input.js +166 -54
  60. package/dist/portable/index.d.ts +4 -0
  61. package/dist/portable/index.js +3 -0
  62. package/dist/portable/page.d.ts +38 -0
  63. package/dist/portable/page.js +361 -0
  64. package/dist/portable/theme.d.ts +19 -0
  65. package/dist/portable/theme.js +40 -0
  66. package/dist/portable/tree.d.ts +10 -0
  67. package/dist/portable/tree.js +96 -0
  68. package/dist/range.d.ts +3 -0
  69. package/dist/range.js +16 -5
  70. package/dist/rate.d.ts +46 -0
  71. package/dist/rate.js +193 -0
  72. package/dist/resizable.d.ts +97 -0
  73. package/dist/resizable.js +426 -0
  74. package/dist/skeleton.d.ts +41 -0
  75. package/dist/skeleton.js +141 -0
  76. package/dist/steps.d.ts +45 -0
  77. package/dist/steps.js +203 -0
  78. package/dist/table.d.ts +106 -0
  79. package/dist/table.js +689 -0
  80. package/dist/tabs.d.ts +7 -0
  81. package/dist/tabs.js +90 -16
  82. package/dist/tag.d.ts +55 -0
  83. package/dist/tag.js +225 -0
  84. package/dist/time-picker.d.ts +62 -0
  85. package/dist/time-picker.js +298 -0
  86. package/dist/timeline.d.ts +48 -0
  87. package/dist/timeline.js +201 -0
  88. package/dist/toast.d.ts +55 -0
  89. package/dist/toast.js +224 -0
  90. package/dist/tour.d.ts +89 -0
  91. package/dist/tour.js +306 -0
  92. package/dist/virtual-keyboard.d.ts +95 -0
  93. package/dist/virtual-keyboard.js +432 -0
  94. package/dist/virtual-list.js +12 -10
  95. package/dist/virtual-mouse.d.ts +82 -0
  96. package/dist/virtual-mouse.js +358 -0
  97. package/dist/watermark.d.ts +44 -0
  98. package/dist/watermark.js +148 -0
  99. package/package.json +135 -7
@@ -0,0 +1,93 @@
1
+ import { equalData, snapshot } from './data.js';
2
+ import { HYUIError, hyKey, hyValidateProps } from './validation.js';
3
+ /** Controlled Select/Tabs semantics. Views report user actions, never delayed setter echoes. */
4
+ export class HYSelectionController {
5
+ key;
6
+ emit;
7
+ #props;
8
+ #view;
9
+ #off;
10
+ #applying = false;
11
+ #disposed = false;
12
+ #choosing = false;
13
+ #generation = 0;
14
+ #transaction = 0;
15
+ #lastApplied;
16
+ constructor(key, props, emit) {
17
+ this.key = key;
18
+ this.emit = emit;
19
+ hyKey(key);
20
+ this.update(props);
21
+ }
22
+ update(props) {
23
+ if (this.#disposed)
24
+ return;
25
+ hyValidateProps('Select', props, { key: this.key });
26
+ if (equalData(props, this.#props))
27
+ return;
28
+ this.#props = snapshot(props);
29
+ this.#generation++;
30
+ this.#apply();
31
+ }
32
+ #apply() {
33
+ if (!this.#view || this.#disposed || equalData(this.#lastApplied, this.#props))
34
+ return;
35
+ this.#applying = true;
36
+ try {
37
+ this.#view.apply(this.#props);
38
+ this.#lastApplied = this.#props;
39
+ }
40
+ finally {
41
+ this.#applying = false;
42
+ }
43
+ }
44
+ attach(view) {
45
+ if (this.#disposed || this.#view)
46
+ throw new HYUIError('lifecycle', 'Selection disposed or already attached', { key: this.key });
47
+ this.#view = view;
48
+ this.#off = view.listen((value, reason = 'pointer') => this.choose(value, reason));
49
+ this.#apply();
50
+ }
51
+ choose(value, reason = 'pointer') {
52
+ if (this.#disposed || this.#applying || this.#choosing || this.#props.disabled)
53
+ return false;
54
+ const option = this.#props.options.find(item => item.value === value);
55
+ if (!option || option.disabled || value === this.#props.value)
56
+ return false;
57
+ this.#lastApplied = undefined;
58
+ this.#choosing = true;
59
+ const transaction = ++this.#transaction;
60
+ try {
61
+ this.emit({ type: 'valueChange', key: this.key, value, reason, transaction });
62
+ if (this.#disposed)
63
+ return false;
64
+ this.emit({ type: 'commit', key: this.key, value, reason, transaction });
65
+ return true;
66
+ }
67
+ finally {
68
+ this.#choosing = false;
69
+ this.#apply();
70
+ }
71
+ }
72
+ async pick(open, reason = 'pointer') {
73
+ if (this.#disposed || this.#props.disabled)
74
+ return false;
75
+ const generation = ++this.#generation;
76
+ const value = await open();
77
+ if (this.#disposed || generation !== this.#generation || value === null)
78
+ return false;
79
+ return this.choose(value, reason);
80
+ }
81
+ cancel() { this.#generation++; }
82
+ dispose() {
83
+ if (this.#disposed)
84
+ return;
85
+ this.#disposed = true;
86
+ this.cancel();
87
+ const off = this.#off;
88
+ this.#off = undefined;
89
+ this.#view = undefined;
90
+ off?.();
91
+ }
92
+ }
93
+ //# sourceMappingURL=selection.js.map
@@ -0,0 +1,31 @@
1
+ import type { HYReason, HYTextProps, HYUIEvent } from './types.js';
2
+ export interface HYTextViewState {
3
+ readonly props: HYTextProps;
4
+ readonly value: string;
5
+ readonly composing: boolean;
6
+ }
7
+ export interface HYTextView {
8
+ apply(state: HYTextViewState): void;
9
+ }
10
+ /** Local draft/IME state only. The application accepts or rejects commit through props/revision. */
11
+ export declare class HYTextController {
12
+ #private;
13
+ readonly key: string;
14
+ private readonly emit;
15
+ readonly multiline: boolean;
16
+ constructor(key: string, props: HYTextProps, emit: (event: HYUIEvent) => void, multiline?: boolean, revision?: number);
17
+ get value(): string;
18
+ get composing(): boolean;
19
+ update(props: HYTextProps, revision?: number): void;
20
+ attach(view: HYTextView): void;
21
+ input(value: string, reason?: HYReason): boolean;
22
+ compositionStart(reason?: HYReason): boolean;
23
+ compositionEnd(value: string, reason?: HYReason): boolean;
24
+ commit(reason?: HYReason): boolean;
25
+ /** The adapter supplies wasComposing from its native event; confirmation Enter never submits. */
26
+ enter(wasComposing?: boolean): boolean;
27
+ focus(reason?: HYReason): void;
28
+ blur(reason?: HYReason): void;
29
+ cancel(reason?: HYReason): void;
30
+ dispose(): void;
31
+ }
@@ -0,0 +1,154 @@
1
+ import { equalData, snapshot } from './data.js';
2
+ import { HYUIError, hyKey, hyValidateProps } from './validation.js';
3
+ /** Local draft/IME state only. The application accepts or rejects commit through props/revision. */
4
+ export class HYTextController {
5
+ key;
6
+ emit;
7
+ multiline;
8
+ #props;
9
+ #revision = -1;
10
+ #draft = '';
11
+ #composing = false;
12
+ #pending;
13
+ #transaction = 0;
14
+ #active = 0;
15
+ #disposed = false;
16
+ #applying = false;
17
+ #view;
18
+ #applied;
19
+ constructor(key, props, emit, multiline = false, revision = 0) {
20
+ this.key = key;
21
+ this.emit = emit;
22
+ this.multiline = multiline;
23
+ hyKey(key);
24
+ this.update(props, revision);
25
+ }
26
+ get value() { return this.#draft; }
27
+ get composing() { return this.#composing; }
28
+ update(props, revision = this.#revision) {
29
+ if (this.#disposed)
30
+ return;
31
+ hyValidateProps(this.multiline ? 'TextArea' : 'TextInput', props, { key: this.key });
32
+ if (!Number.isSafeInteger(revision) || revision < 0)
33
+ throw new HYUIError('invalid-props', 'Invalid application revision', { key: this.key });
34
+ if (revision < this.#revision)
35
+ return;
36
+ const changed = !this.#props || props.value !== this.#props.value;
37
+ if (this.#props && changed && revision === this.#revision)
38
+ throw new HYUIError('invalid-props', 'Changed accepted value requires a newer revision', { key: this.key });
39
+ this.#props = snapshot(props);
40
+ this.#revision = revision;
41
+ if (changed) {
42
+ if (this.#composing)
43
+ this.#pending = { value: props.value, revision };
44
+ else {
45
+ this.#draft = props.value;
46
+ this.#active = 0;
47
+ this.#pending = undefined;
48
+ }
49
+ }
50
+ if (props.disabled || props.readOnly) {
51
+ if (this.#pending)
52
+ this.#draft = this.#pending.value;
53
+ this.#composing = false;
54
+ this.#pending = undefined;
55
+ this.#active = 0;
56
+ }
57
+ // Reapplying the accepted value never discards an unaccepted draft or its selection.
58
+ this.#apply();
59
+ }
60
+ attach(view) {
61
+ if (this.#view || this.#disposed)
62
+ throw new HYUIError('lifecycle', 'Text disposed or already attached', { key: this.key });
63
+ this.#view = view;
64
+ this.#apply();
65
+ }
66
+ #apply() {
67
+ if (!this.#view || this.#disposed)
68
+ return;
69
+ const state = snapshot({ props: this.#props, value: this.#draft, composing: this.#composing });
70
+ if (equalData(state, this.#applied))
71
+ return;
72
+ this.#applying = true;
73
+ try {
74
+ this.#view.apply(state);
75
+ this.#applied = state;
76
+ }
77
+ finally {
78
+ this.#applying = false;
79
+ }
80
+ }
81
+ #enabled() { return !this.#disposed && !this.#applying && !this.#props.disabled && !this.#props.readOnly; }
82
+ #send(type, reason, value) {
83
+ if (this.#disposed)
84
+ return;
85
+ this.emit({ key: this.key, type, reason, transaction: this.#active, composing: this.#composing, ...(value === undefined ? {} : { value }) });
86
+ }
87
+ input(value, reason = 'keyboard') {
88
+ if (!this.#enabled() || typeof value !== 'string' || value === this.#draft)
89
+ return false;
90
+ this.#draft = value;
91
+ this.#active ||= ++this.#transaction;
92
+ this.#send(this.#composing ? 'compositionUpdate' : 'valueChange', reason, value);
93
+ this.#apply();
94
+ return true;
95
+ }
96
+ compositionStart(reason = 'keyboard') {
97
+ if (!this.#enabled() || this.#composing)
98
+ return false;
99
+ this.#composing = true;
100
+ this.#active ||= ++this.#transaction;
101
+ this.#send('compositionStart', reason);
102
+ return true;
103
+ }
104
+ compositionEnd(value, reason = 'keyboard') {
105
+ if (this.#disposed || this.#applying || !this.#composing || typeof value !== 'string')
106
+ return false;
107
+ this.#draft = value;
108
+ this.#composing = false;
109
+ this.#send('compositionEnd', reason, value);
110
+ this.#send('valueChange', reason, value);
111
+ if (this.#pending) {
112
+ // A newer authoritative update wins; an acceptance during emit can supersede it.
113
+ if (this.#pending.revision === this.#revision)
114
+ this.#draft = this.#pending.value;
115
+ this.#pending = undefined;
116
+ this.#active = 0;
117
+ }
118
+ this.#apply();
119
+ return true;
120
+ }
121
+ commit(reason = 'keyboard') {
122
+ if (!this.#enabled() || this.#composing || !this.#active)
123
+ return false;
124
+ const transaction = this.#active;
125
+ this.#active = 0;
126
+ if (this.#draft === this.#props.value)
127
+ return false;
128
+ this.emit({ key: this.key, type: 'commit', value: this.#draft, reason, transaction, composing: false });
129
+ this.#apply();
130
+ return true;
131
+ }
132
+ /** The adapter supplies wasComposing from its native event; confirmation Enter never submits. */
133
+ enter(wasComposing = false) { return !this.multiline && !wasComposing && this.commit('keyboard'); }
134
+ focus(reason = 'keyboard') { if (!this.#disposed && !this.#applying)
135
+ this.#send('focus', reason); }
136
+ blur(reason = 'keyboard') {
137
+ if (this.#disposed || this.#applying)
138
+ return;
139
+ this.commit(reason);
140
+ this.#send('blur', reason);
141
+ }
142
+ cancel(reason = 'keyboard') {
143
+ if (this.#disposed || this.#applying)
144
+ return;
145
+ this.#draft = this.#props.value;
146
+ this.#composing = false;
147
+ this.#pending = undefined;
148
+ this.#send('cancel', reason);
149
+ this.#active = 0;
150
+ this.#apply();
151
+ }
152
+ dispose() { this.#disposed = true; this.#view = undefined; this.#pending = undefined; this.#active = 0; }
153
+ }
154
+ //# sourceMappingURL=text.js.map
@@ -0,0 +1,250 @@
1
+ /** Portable UI protocol 1, additive G03 schema 1.1. No platform imports. */
2
+ export type HYNodeKey = string;
3
+ export type HYDispose = () => void;
4
+ export type HYReason = 'pointer' | 'keyboard' | 'accessibility';
5
+ export interface HYOption {
6
+ readonly value: string;
7
+ readonly label: string;
8
+ readonly disabled?: boolean;
9
+ }
10
+ export interface HYSelectionProps {
11
+ readonly value: string;
12
+ readonly options: readonly HYOption[];
13
+ readonly disabled?: boolean;
14
+ }
15
+ export interface HYSelectionEvent {
16
+ readonly type: 'valueChange' | 'commit';
17
+ readonly key: HYNodeKey;
18
+ readonly value: string;
19
+ readonly reason: HYReason;
20
+ readonly transaction: number;
21
+ }
22
+ export interface HYSelectionView {
23
+ apply(props: HYSelectionProps): void;
24
+ listen(listener: (value: string, reason?: HYReason) => void): HYDispose;
25
+ }
26
+ export interface HYStore<S, A> {
27
+ getSnapshot(): Readonly<S>;
28
+ dispatch(action: A): void;
29
+ subscribe<T>(select: (state: Readonly<S>) => T, notify: (value: T) => void, equal?: (a: T, b: T) => boolean): HYDispose;
30
+ transaction(run: () => void): void;
31
+ dispose(): void;
32
+ }
33
+ export interface HYCancelSignal {
34
+ readonly aborted: boolean;
35
+ onAbort(callback: () => void): HYDispose;
36
+ }
37
+ export interface HYRequestContext {
38
+ readonly session: string;
39
+ readonly revision: number;
40
+ readonly request: number;
41
+ readonly signal: HYCancelSignal;
42
+ }
43
+ export type HYLength = number | 'auto';
44
+ export interface HYLayout {
45
+ readonly width?: HYLength;
46
+ readonly height?: HYLength;
47
+ readonly minWidth?: number;
48
+ readonly maxWidth?: number;
49
+ readonly minHeight?: number;
50
+ readonly maxHeight?: number;
51
+ readonly padding?: readonly [number, number, number, number];
52
+ readonly gap?: number;
53
+ readonly grow?: number;
54
+ readonly align?: 'start' | 'center' | 'end' | 'stretch';
55
+ readonly columns?: readonly (number | 'auto' | {
56
+ readonly grow: number;
57
+ })[];
58
+ readonly rows?: readonly (number | 'auto' | {
59
+ readonly grow: number;
60
+ })[];
61
+ readonly row?: number;
62
+ readonly column?: number;
63
+ readonly clip?: boolean;
64
+ }
65
+ export interface HYAccessibility {
66
+ readonly label: string;
67
+ readonly description?: string;
68
+ readonly error?: string;
69
+ readonly role?: 'button' | 'text' | 'textbox' | 'checkbox' | 'tab' | 'dialog' | 'image' | 'slider' | 'list' | 'tree';
70
+ }
71
+ export interface HYCommonProps {
72
+ readonly layout?: HYLayout;
73
+ readonly a11y?: HYAccessibility;
74
+ readonly visible?: boolean;
75
+ }
76
+ export interface HYTextProps {
77
+ readonly value: string;
78
+ readonly disabled?: boolean;
79
+ readonly readOnly?: boolean;
80
+ readonly placeholder?: string;
81
+ readonly secure?: boolean;
82
+ }
83
+ export interface HYResource {
84
+ readonly id: string;
85
+ readonly alt: string;
86
+ }
87
+ export interface HYComponentProps {
88
+ Row: HYCommonProps;
89
+ Column: HYCommonProps;
90
+ Grid: HYCommonProps;
91
+ Overlay: HYCommonProps;
92
+ Scroll: HYCommonProps & {
93
+ readonly axis: 'horizontal' | 'vertical';
94
+ };
95
+ Text: HYCommonProps & {
96
+ readonly text: string;
97
+ readonly wrap?: boolean;
98
+ };
99
+ Image: HYCommonProps & {
100
+ readonly resource: HYResource;
101
+ readonly fit?: 'contain' | 'cover';
102
+ };
103
+ Icon: HYCommonProps & {
104
+ readonly resource: HYResource;
105
+ readonly systemName?: string;
106
+ };
107
+ Button: HYCommonProps & {
108
+ readonly text: string;
109
+ readonly disabled?: boolean;
110
+ readonly busy?: boolean;
111
+ };
112
+ Checkbox: HYCommonProps & {
113
+ readonly checked: boolean;
114
+ readonly disabled?: boolean;
115
+ readonly text: string;
116
+ };
117
+ RadioGroup: HYCommonProps & HYSelectionProps;
118
+ Rate: HYCommonProps & {
119
+ readonly value: number;
120
+ readonly count: number;
121
+ readonly disabled?: boolean;
122
+ readonly readOnly?: boolean;
123
+ };
124
+ Badge: HYCommonProps & {
125
+ readonly text: string;
126
+ };
127
+ Divider: HYCommonProps & {
128
+ readonly text?: string;
129
+ };
130
+ Toggle: HYCommonProps & {
131
+ readonly checked: boolean;
132
+ readonly disabled?: boolean;
133
+ };
134
+ Select: HYCommonProps & HYSelectionProps;
135
+ Tabs: HYCommonProps & HYSelectionProps;
136
+ TextInput: HYCommonProps & HYTextProps;
137
+ TextArea: HYCommonProps & Omit<HYTextProps, 'secure'>;
138
+ Slider: HYCommonProps & {
139
+ readonly value: number;
140
+ readonly min: number;
141
+ readonly max: number;
142
+ readonly step: number;
143
+ readonly disabled?: boolean;
144
+ };
145
+ Dialog: HYCommonProps & {
146
+ readonly open: boolean;
147
+ readonly title: string;
148
+ readonly dismissible?: boolean;
149
+ };
150
+ FormGroup: HYCommonProps & {
151
+ readonly label: string;
152
+ readonly error?: string;
153
+ };
154
+ PlatformView: HYCommonProps & {
155
+ readonly slot: string;
156
+ readonly resourceId: string;
157
+ };
158
+ }
159
+ export type HYComponentKind = keyof HYComponentProps;
160
+ export type HYNode = {
161
+ [K in HYComponentKind]: {
162
+ readonly key: HYNodeKey;
163
+ readonly kind: K;
164
+ readonly props: Readonly<HYComponentProps[K]>;
165
+ readonly source?: HYSourceLocation;
166
+ readonly requires?: readonly HYFeature[];
167
+ readonly children?: readonly HYNode[];
168
+ readonly slots?: Readonly<Record<string, readonly HYNode[]>>;
169
+ };
170
+ }[HYComponentKind];
171
+ export interface HYUIEvent {
172
+ readonly key: HYNodeKey;
173
+ readonly type: 'activate' | 'valueChange' | 'commit' | 'cancel' | 'focus' | 'blur' | 'compositionStart' | 'compositionUpdate' | 'compositionEnd';
174
+ readonly value?: string | number | boolean;
175
+ readonly reason: HYReason;
176
+ readonly transaction: number;
177
+ readonly composing?: boolean;
178
+ }
179
+ export type HYMutation = {
180
+ readonly type: 'create';
181
+ readonly node: HYNode;
182
+ } | {
183
+ readonly type: 'update';
184
+ readonly node: HYNode;
185
+ } | {
186
+ readonly type: 'insert' | 'move';
187
+ readonly key: HYNodeKey;
188
+ readonly parent: HYNodeKey | null;
189
+ readonly before: HYNodeKey | null;
190
+ readonly slot?: string;
191
+ } | {
192
+ readonly type: 'remove';
193
+ readonly key: HYNodeKey;
194
+ };
195
+ export interface HYCapabilities {
196
+ readonly contract: 1;
197
+ readonly backend: 'web' | 'nativescript' | 'desktop';
198
+ readonly components: readonly HYComponentKind[];
199
+ readonly features: readonly string[];
200
+ }
201
+ export interface HYRenderer {
202
+ readonly capabilities: HYCapabilities;
203
+ mount(emit: (event: HYUIEvent) => void): void;
204
+ commit(revision: number, mutations: readonly HYMutation[]): void;
205
+ focus(key: HYNodeKey): void;
206
+ suspend(): void;
207
+ resume(): void;
208
+ dispose(): void;
209
+ }
210
+ export interface HYPlatformView {
211
+ mount(): void;
212
+ update(resourceId: string): void;
213
+ layout(bounds: {
214
+ readonly x: number;
215
+ readonly y: number;
216
+ readonly width: number;
217
+ readonly height: number;
218
+ readonly scale: number;
219
+ }): void;
220
+ visible(value: boolean): void;
221
+ focus(): void;
222
+ dispose(): void;
223
+ }
224
+ export interface HYTheme {
225
+ readonly color: Readonly<Record<'text' | 'muted' | 'surface' | 'input' | 'accent' | 'danger' | 'border' | 'focus', string>>;
226
+ readonly fontSize: number;
227
+ readonly lineHeight: number;
228
+ readonly gap: number;
229
+ readonly radius: number;
230
+ }
231
+ export interface HYSourceLocation {
232
+ readonly file: string;
233
+ readonly line?: number;
234
+ }
235
+ export type HYFeature = 'text.composition' | 'text.selection' | 'text.secure' | 'accessibility' | 'icons.system' | 'layout.rtl' | 'theme.highContrast' | 'motion.reduced';
236
+ export interface HYDiagnosticContext {
237
+ readonly key?: string;
238
+ readonly property?: string;
239
+ readonly source?: HYSourceLocation;
240
+ readonly operation?: string;
241
+ readonly revision?: number;
242
+ }
243
+ export type HYDiagnosticCode = 'invalid-props' | 'duplicate-key' | 'capability' | 'lifecycle' | 'renderer';
244
+ export interface HYBounds {
245
+ readonly x: number;
246
+ readonly y: number;
247
+ readonly width: number;
248
+ readonly height: number;
249
+ readonly scale: number;
250
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1,24 @@
1
+ import type { HYCapabilities, HYComponentKind, HYComponentProps, HYDiagnosticCode, HYDiagnosticContext, HYFeature, HYNode, HYSourceLocation } from './types.js';
2
+ export declare class HYUIError extends Error {
3
+ readonly code: HYDiagnosticCode;
4
+ readonly context: Readonly<HYDiagnosticContext>;
5
+ constructor(code: HYDiagnosticCode, message: string, context?: HYDiagnosticContext, cause?: unknown);
6
+ }
7
+ export declare const HY_FEATURES: readonly HYFeature[];
8
+ export declare const HY_COMPONENTS: readonly HYComponentKind[];
9
+ export declare function hyValidateCapabilities(capabilities: HYCapabilities): void;
10
+ export declare function hySupports(capabilities: HYCapabilities, feature: HYFeature): boolean;
11
+ /** Internal immutable hand-off. Mutable and merely shallow-frozen inputs are always validated. */
12
+ export declare function snapshotValidatedProps<K extends HYComponentKind>(kind: K, props: HYComponentProps[K], context: HYDiagnosticContext, capabilities: HYCapabilities): HYComponentProps[K];
13
+ export declare function hyValidateProps<K extends HYComponentKind>(kind: K, props: HYComponentProps[K], context?: HYDiagnosticContext, capabilities?: HYCapabilities): void;
14
+ /** Escaped, stable backend key. Author keys are unique across all slots of one parent. */
15
+ export declare function hyKey(...parts: readonly string[]): string;
16
+ export declare function hyValidateNode(node: HYNode, capabilities?: HYCapabilities): HYNode;
17
+ export declare function hyNode<K extends HYComponentKind>(kind: K, key: string, props: HYComponentProps[K], content?: {
18
+ readonly children?: readonly HYNode[];
19
+ readonly slots?: Readonly<Record<string, readonly HYNode[]>>;
20
+ readonly source?: HYSourceLocation;
21
+ readonly requires?: readonly HYFeature[];
22
+ }): Extract<HYNode, {
23
+ kind: K;
24
+ }>;