@gadxr/ui 0.0.0-stage → 0.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.
Files changed (114) hide show
  1. package/LICENSE +21 -0
  2. package/dist/Avatar.svelte +136 -0
  3. package/dist/Avatar.svelte.d.ts +13 -0
  4. package/dist/Button.svelte +29 -0
  5. package/dist/Button.svelte.d.ts +4 -0
  6. package/dist/Button2D.svelte +77 -0
  7. package/dist/Button2D.svelte.d.ts +4 -0
  8. package/dist/Button3D.svelte +98 -0
  9. package/dist/Button3D.svelte.d.ts +4 -0
  10. package/dist/ButtonGroup.svelte +59 -0
  11. package/dist/ButtonGroup.svelte.d.ts +17 -0
  12. package/dist/Checkbox.svelte +209 -0
  13. package/dist/Checkbox.svelte.d.ts +14 -0
  14. package/dist/DimensionScope.svelte +7 -0
  15. package/dist/DimensionScope.svelte.d.ts +9 -0
  16. package/dist/Input.svelte +293 -0
  17. package/dist/Input.svelte.d.ts +23 -0
  18. package/dist/Key3D.svelte +67 -0
  19. package/dist/Key3D.svelte.d.ts +13 -0
  20. package/dist/Keyboard.svelte +167 -0
  21. package/dist/Keyboard.svelte.d.ts +9 -0
  22. package/dist/Menu.svelte +193 -0
  23. package/dist/Menu.svelte.d.ts +23 -0
  24. package/dist/Modal.svelte +103 -0
  25. package/dist/Modal.svelte.d.ts +16 -0
  26. package/dist/Panel.svelte +132 -0
  27. package/dist/Panel.svelte.d.ts +19 -0
  28. package/dist/Pressable3D.svelte +82 -0
  29. package/dist/Pressable3D.svelte.d.ts +28 -0
  30. package/dist/ProgressBar.svelte +153 -0
  31. package/dist/ProgressBar.svelte.d.ts +16 -0
  32. package/dist/RadialMenu.svelte +322 -0
  33. package/dist/RadialMenu.svelte.d.ts +28 -0
  34. package/dist/Rule3D.svelte +17 -0
  35. package/dist/Rule3D.svelte.d.ts +9 -0
  36. package/dist/Scene3D.svelte +24 -0
  37. package/dist/Scene3D.svelte.d.ts +11 -0
  38. package/dist/Slider.svelte +209 -0
  39. package/dist/Slider.svelte.d.ts +17 -0
  40. package/dist/Space3D.svelte +6 -0
  41. package/dist/Space3D.svelte.d.ts +7 -0
  42. package/dist/Spinner.svelte +64 -0
  43. package/dist/Spinner.svelte.d.ts +10 -0
  44. package/dist/Stack.svelte +41 -0
  45. package/dist/Stack.svelte.d.ts +15 -0
  46. package/dist/StackScope.svelte +7 -0
  47. package/dist/StackScope.svelte.d.ts +9 -0
  48. package/dist/Surface.svelte +152 -0
  49. package/dist/Surface.svelte.d.ts +30 -0
  50. package/dist/Tab.svelte +40 -0
  51. package/dist/Tab.svelte.d.ts +10 -0
  52. package/dist/Tabs.svelte +145 -0
  53. package/dist/Tabs.svelte.d.ts +13 -0
  54. package/dist/Tag.svelte +71 -0
  55. package/dist/Tag.svelte.d.ts +12 -0
  56. package/dist/Text.svelte +75 -0
  57. package/dist/Text.svelte.d.ts +4 -0
  58. package/dist/TextLine3D.svelte +84 -0
  59. package/dist/TextLine3D.svelte.d.ts +19 -0
  60. package/dist/ThemeProvider.svelte +7 -0
  61. package/dist/ThemeProvider.svelte.d.ts +9 -0
  62. package/dist/Toaster.svelte +104 -0
  63. package/dist/Toaster.svelte.d.ts +11 -0
  64. package/dist/Tooltip.svelte +174 -0
  65. package/dist/Tooltip.svelte.d.ts +14 -0
  66. package/dist/aframe/frame.d.ts +1 -0
  67. package/dist/aframe/frame.js +37 -0
  68. package/dist/aframe/index.d.ts +1 -0
  69. package/dist/aframe/index.js +19 -0
  70. package/dist/aframe/measure.d.ts +3 -0
  71. package/dist/aframe/measure.js +42 -0
  72. package/dist/aframe/placement.d.ts +88 -0
  73. package/dist/aframe/placement.js +163 -0
  74. package/dist/aframe/rounded.d.ts +61 -0
  75. package/dist/aframe/rounded.js +121 -0
  76. package/dist/aframe/scene.d.ts +9 -0
  77. package/dist/aframe/scene.js +101 -0
  78. package/dist/assets/Geist-OFL.txt +93 -0
  79. package/dist/assets/Geist-Regular.ttf +0 -0
  80. package/dist/button-style.d.ts +22 -0
  81. package/dist/button-style.js +34 -0
  82. package/dist/component-style.d.ts +79 -0
  83. package/dist/component-style.js +129 -0
  84. package/dist/context.d.ts +16 -0
  85. package/dist/context.js +26 -0
  86. package/dist/fonts.css +7 -0
  87. package/dist/fonts.d.ts +2 -0
  88. package/dist/fonts.js +7 -0
  89. package/dist/index.d.ts +40 -0
  90. package/dist/index.js +40 -0
  91. package/dist/keyboard-layout.d.ts +28 -0
  92. package/dist/keyboard-layout.js +77 -0
  93. package/dist/layout-math.d.ts +20 -0
  94. package/dist/layout-math.js +22 -0
  95. package/dist/layout.svelte.d.ts +17 -0
  96. package/dist/layout.svelte.js +58 -0
  97. package/dist/radial-math.d.ts +33 -0
  98. package/dist/radial-math.js +90 -0
  99. package/dist/tabs-context.d.ts +13 -0
  100. package/dist/tabs-context.js +6 -0
  101. package/dist/text-edit.d.ts +46 -0
  102. package/dist/text-edit.js +133 -0
  103. package/dist/text-focus.svelte.d.ts +24 -0
  104. package/dist/text-focus.svelte.js +102 -0
  105. package/dist/theme.d.ts +335 -0
  106. package/dist/theme.js +312 -0
  107. package/dist/toast.svelte.d.ts +24 -0
  108. package/dist/toast.svelte.js +30 -0
  109. package/dist/types.d.ts +25 -0
  110. package/dist/types.js +1 -0
  111. package/dist/xr.svelte.d.ts +9 -0
  112. package/dist/xr.svelte.js +24 -0
  113. package/package.json +44 -3
  114. package/README.md +0 -3
@@ -0,0 +1,102 @@
1
+ import { keyToAction } from './text-edit';
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ class TextFocus {
4
+ // Raw: a deep $state would hold a proxy, and `current === field` would never match.
5
+ current = $state.raw(null);
6
+ // Mounted <Keyboard> roots: pressing inside them keeps focus too.
7
+ keyboards = new Set();
8
+ focus(field) {
9
+ if (this.current === field)
10
+ return;
11
+ this.current?.done();
12
+ this.current = field;
13
+ listen(field.el);
14
+ }
15
+ blur(field) {
16
+ if (this.current === field)
17
+ this.current = null;
18
+ }
19
+ contains(target) {
20
+ if (!(target instanceof Element))
21
+ return false;
22
+ if (this.current?.el?.contains(target))
23
+ return true;
24
+ for (const keyboard of this.keyboards)
25
+ if (keyboard.contains(target))
26
+ return true;
27
+ return false;
28
+ }
29
+ }
30
+ export const textFocus = new TextFocus();
31
+ // Native fields (2D Inputs, other HTML) keep their own keys.
32
+ function isNativeEditable(target) {
33
+ return target instanceof HTMLElement && (target.isContentEditable || /^(INPUT|TEXTAREA|SELECT)$/.test(target.tagName));
34
+ }
35
+ // Capture phase, before the page's own shortcuts and movement controls (all on window):
36
+ // while a 3D field has focus, it gets every key except Cmd/Ctrl shortcuts.
37
+ function onKeydown(event) {
38
+ const field = textFocus.current;
39
+ if (!field || isNativeEditable(event.target) || event.ctrlKey || event.metaKey)
40
+ return;
41
+ event.stopImmediatePropagation();
42
+ event.preventDefault();
43
+ takenKeys.add(keyId(event));
44
+ const action = keyToAction(event);
45
+ if (action === 'enter')
46
+ field.enter();
47
+ else if (action === 'escape')
48
+ field.cancel();
49
+ else if (action)
50
+ field.edit(action);
51
+ }
52
+ // The keyup of a key the field took is taken too, even once editing has ended (Enter,
53
+ // Escape): A-Frame's keyboard-shortcuts acts on keyup (F enters VR, which on desktop is
54
+ // fullscreen). A key already down before focus keeps its keyup, so movement controls
55
+ // see it released.
56
+ const takenKeys = new Set();
57
+ const keyId = (event) => event.code || event.key;
58
+ function onKeyup(event) {
59
+ if (!takenKeys.delete(keyId(event)))
60
+ return;
61
+ event.stopImmediatePropagation();
62
+ event.preventDefault();
63
+ }
64
+ function onPaste(event) {
65
+ const field = textFocus.current;
66
+ const text = event.clipboardData?.getData('text/plain');
67
+ if (!field || isNativeEditable(event.target) || !text)
68
+ return;
69
+ event.preventDefault();
70
+ field.edit({ type: 'insert', text });
71
+ }
72
+ // Any cursor press (mouse or VR laser) on something other than the field or the
73
+ // keyboard — including on nothing — ends editing. The cursor emits mousedown on itself
74
+ // with what it hit (`intersectedEl`, no `cursorEl`), and that bubbles to the scene.
75
+ function onCursorDown(event) {
76
+ const detail = event.detail;
77
+ if (!textFocus.current || !detail || !event.target?.components?.cursor)
78
+ return;
79
+ if (!textFocus.contains(detail.intersectedEl))
80
+ textFocus.current.done();
81
+ }
82
+ // Clicking HTML outside the 3D canvas ends editing as well.
83
+ function onPointerDown(event) {
84
+ if (textFocus.current && !(event.target instanceof HTMLCanvasElement))
85
+ textFocus.current.done();
86
+ }
87
+ let windowListening = false;
88
+ const scenes = new WeakSet();
89
+ function listen(el) {
90
+ if (!windowListening) {
91
+ windowListening = true;
92
+ window.addEventListener('keydown', onKeydown, true);
93
+ window.addEventListener('keyup', onKeyup, true);
94
+ window.addEventListener('pointerdown', onPointerDown, true);
95
+ document.addEventListener('paste', onPaste);
96
+ }
97
+ const scene = el?.sceneEl ?? el?.closest('a-scene');
98
+ if (scene && !scenes.has(scene)) {
99
+ scenes.add(scene);
100
+ scene.addEventListener('mousedown', onCursorDown);
101
+ }
102
+ }
@@ -0,0 +1,335 @@
1
+ export type ButtonKind = 'primary' | 'secondary' | 'tertiary';
2
+ export type ButtonSize = 'mini' | 'compact' | 'default' | 'large';
3
+ export type ButtonShape = 'default' | 'pill' | 'round' | 'circle' | 'square';
4
+ export type Dimension = '2d' | '3d';
5
+ export type Material3D = 'glass' | 'solid' | 'none';
6
+ export type TagKind = 'neutral' | 'accent' | 'positive' | 'warning' | 'negative';
7
+ export type TagVariant = 'solid' | 'light';
8
+ export type TagSize = 'small' | 'medium';
9
+ export type SpinnerSize = 'small' | 'medium' | 'large';
10
+ export type ToastKind = 'info' | 'positive' | 'warning' | 'negative';
11
+ export type ProgressBarSize = 'small' | 'medium' | 'large';
12
+ export type AvatarSize = 'small' | 'medium' | 'large';
13
+ export type AvatarStatus = 'online' | 'away' | 'busy' | 'offline';
14
+ export type TooltipPlacement = 'top' | 'bottom' | 'left' | 'right';
15
+ export type TypographyVariant = 'LabelXSmall' | 'LabelSmall' | 'LabelMedium' | 'LabelLarge' | 'HeadingSmall' | 'HeadingMedium' | 'ParagraphMedium';
16
+ export type Font = {
17
+ fontSize: number;
18
+ lineHeight: number;
19
+ fontWeight: number;
20
+ };
21
+ type TagColors = {
22
+ solidFill: string;
23
+ solidText: string;
24
+ lightFill: string;
25
+ lightText: string;
26
+ };
27
+ type KindColors = {
28
+ fill: string;
29
+ text: string;
30
+ hover: string;
31
+ active: string;
32
+ selectedFill: string;
33
+ selectedText: string;
34
+ };
35
+ export declare const defaultTheme: {
36
+ name: string;
37
+ colors: {
38
+ contentPrimary: string;
39
+ contentSecondary: string;
40
+ contentTertiary: string;
41
+ backgroundPrimary: string;
42
+ backgroundSecondary: string;
43
+ button: Record<ButtonKind, KindColors>;
44
+ buttonDisabledFill: string;
45
+ buttonDisabledText: string;
46
+ panel: {
47
+ fill: string;
48
+ border: string;
49
+ };
50
+ checkbox: {
51
+ border: string;
52
+ fill3d: string;
53
+ fillChecked: string;
54
+ mark: string;
55
+ toggleTrack: string;
56
+ toggleTrackChecked: string;
57
+ toggleKnob: string;
58
+ };
59
+ slider: {
60
+ track: string;
61
+ fill: string;
62
+ thumb: string;
63
+ };
64
+ tag: Record<TagKind, TagColors>;
65
+ spinner: {
66
+ track: string;
67
+ active: string;
68
+ };
69
+ input: {
70
+ fill: string;
71
+ border: string;
72
+ hover: string;
73
+ focus: string;
74
+ error: string;
75
+ text: string;
76
+ placeholder: string;
77
+ caret: string;
78
+ label: string;
79
+ caption: string;
80
+ errorText: string;
81
+ };
82
+ keyboard: {
83
+ fill: string;
84
+ key: string;
85
+ keyHover: string;
86
+ special: string;
87
+ specialHover: string;
88
+ accent: string;
89
+ accentHover: string;
90
+ pressed: string;
91
+ pressedText: string;
92
+ on: string;
93
+ onText: string;
94
+ text: string;
95
+ };
96
+ tabs: {
97
+ text: string;
98
+ textActive: string;
99
+ hover: string;
100
+ indicator: string;
101
+ border: string;
102
+ };
103
+ menu: {
104
+ fill: string;
105
+ border: string;
106
+ hover: string;
107
+ active: string;
108
+ text: string;
109
+ end: string;
110
+ selected: string;
111
+ divider: string;
112
+ };
113
+ modal: {
114
+ fill: string;
115
+ backdrop: string;
116
+ backdropOpacity: number;
117
+ };
118
+ radial: {
119
+ fill: string;
120
+ active: string;
121
+ text: string;
122
+ disabledText: string;
123
+ ring: string;
124
+ };
125
+ toast: Record<ToastKind, {
126
+ fill: string;
127
+ text: string;
128
+ accent: string;
129
+ }>;
130
+ progressBar: {
131
+ track: string;
132
+ fill: string;
133
+ };
134
+ avatar: {
135
+ palette: string[];
136
+ text: string;
137
+ statusRing: string;
138
+ status: Record<AvatarStatus, string>;
139
+ };
140
+ tooltip: {
141
+ fill: string;
142
+ text: string;
143
+ };
144
+ white: string;
145
+ black: string;
146
+ gray50: string;
147
+ gray100: string;
148
+ gray200: string;
149
+ gray300: string;
150
+ gray400: string;
151
+ gray500: string;
152
+ gray600: string;
153
+ gray700: string;
154
+ gray800: string;
155
+ gray900: string;
156
+ accent: string;
157
+ accent400: string;
158
+ negative: string;
159
+ positive: string;
160
+ warning: string;
161
+ };
162
+ sizing: {
163
+ scale0: number;
164
+ scale100: number;
165
+ scale200: number;
166
+ scale300: number;
167
+ scale400: number;
168
+ scale500: number;
169
+ scale550: number;
170
+ scale600: number;
171
+ scale700: number;
172
+ scale800: number;
173
+ scale900: number;
174
+ scale1000: number;
175
+ scale1200: number;
176
+ scale1400: number;
177
+ scale1600: number;
178
+ };
179
+ borders: {
180
+ radius100: number;
181
+ radius200: number;
182
+ radius300: number;
183
+ radius400: number;
184
+ radius500: number;
185
+ buttonBorderRadius: number;
186
+ };
187
+ typography: Record<TypographyVariant, Font> & {
188
+ fontFamily: string;
189
+ font3d: string;
190
+ };
191
+ animation: {
192
+ timing100: number;
193
+ timing200: number;
194
+ timing300: number;
195
+ timing400: number;
196
+ timing500: number;
197
+ easeOutCurve: string;
198
+ easeInOutCurve: string;
199
+ easeOut3d: string;
200
+ easeInOut3d: string;
201
+ };
202
+ button: {
203
+ sizes: Record<ButtonSize, {
204
+ height: number;
205
+ paddingX: number;
206
+ typography: TypographyVariant;
207
+ }>;
208
+ };
209
+ panel: {
210
+ padding: number;
211
+ gap: number;
212
+ radius: number;
213
+ };
214
+ checkbox: {
215
+ box: number;
216
+ boxRadius: number;
217
+ trackWidth: number;
218
+ trackHeight: number;
219
+ knob: number;
220
+ gap: number;
221
+ typography: TypographyVariant;
222
+ };
223
+ slider: {
224
+ width: number;
225
+ trackHeight: number;
226
+ thumb: number;
227
+ gap: number;
228
+ typography: TypographyVariant;
229
+ };
230
+ tag: {
231
+ radius: number;
232
+ sizes: Record<TagSize, {
233
+ height: number;
234
+ paddingX: number;
235
+ typography: TypographyVariant;
236
+ }>;
237
+ };
238
+ tabs: {
239
+ height: number;
240
+ paddingX: number;
241
+ gap: number;
242
+ indicator: number;
243
+ radius: number;
244
+ typography: TypographyVariant;
245
+ };
246
+ menu: {
247
+ itemHeight: number;
248
+ paddingX: number;
249
+ padding: number;
250
+ radius: number;
251
+ itemRadius: number;
252
+ minWidth: number;
253
+ typography: TypographyVariant;
254
+ endTypography: TypographyVariant;
255
+ };
256
+ modal: {
257
+ width: number;
258
+ };
259
+ input: {
260
+ width: number;
261
+ height: number;
262
+ paddingX: number;
263
+ radius: number;
264
+ border: number;
265
+ gap: number;
266
+ caretWidth: number;
267
+ typography: TypographyVariant;
268
+ labelTypography: TypographyVariant;
269
+ captionTypography: TypographyVariant;
270
+ };
271
+ keyboard: {
272
+ key: number;
273
+ gap: number;
274
+ padding: number;
275
+ radius: number;
276
+ typography: TypographyVariant;
277
+ wordTypography: TypographyVariant;
278
+ };
279
+ radial: {
280
+ radius: number;
281
+ innerRadius: number;
282
+ gap: number;
283
+ deadzone: number;
284
+ typography: TypographyVariant;
285
+ };
286
+ toast: {
287
+ width: number;
288
+ padding: number;
289
+ };
290
+ spinner: {
291
+ sizes: Record<SpinnerSize, number>;
292
+ thickness: number;
293
+ };
294
+ progressBar: {
295
+ width: number;
296
+ sizes: Record<ProgressBarSize, number>;
297
+ gap: number;
298
+ typography: TypographyVariant;
299
+ segment: number;
300
+ duration: number;
301
+ };
302
+ avatar: {
303
+ sizes: Record<AvatarSize, number>;
304
+ initials: number;
305
+ status: number;
306
+ statusRing: number;
307
+ };
308
+ tooltip: {
309
+ paddingX: number;
310
+ paddingY: number;
311
+ radius: number;
312
+ gap: number;
313
+ maxWidth: number;
314
+ delay: number;
315
+ typography: TypographyVariant;
316
+ };
317
+ space3d: {
318
+ metersPerPx: number;
319
+ textScale: number;
320
+ depth: number;
321
+ hoverScale: number;
322
+ pressDepth: number;
323
+ material: Record<ButtonKind, Material3D>;
324
+ panelOpacity: number;
325
+ raise: number;
326
+ glassText: string;
327
+ };
328
+ };
329
+ export type Theme = typeof defaultTheme;
330
+ type DeepPartial<T> = {
331
+ [K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
332
+ };
333
+ export declare function createTheme(overrides?: DeepPartial<Theme>, base?: Theme): Theme;
334
+ export declare function toMeters(theme: Theme, px: number): number;
335
+ export {};