@mystravil/hardpoint 0.1.0 → 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 (67) hide show
  1. package/CHANGELOG.md +42 -18
  2. package/LICENSE +25 -25
  3. package/README.md +67 -64
  4. package/dist/base.css +625 -346
  5. package/dist/components/AppShell.svelte +698 -698
  6. package/dist/components/Button.svelte +174 -174
  7. package/dist/components/Checkbox.svelte +235 -198
  8. package/dist/components/Checkbox.svelte.d.ts +9 -2
  9. package/dist/components/CheckboxGroup.svelte +207 -99
  10. package/dist/components/CheckboxGroup.svelte.d.ts +23 -4
  11. package/dist/components/Combobox.svelte +901 -824
  12. package/dist/components/Combobox.svelte.d.ts +10 -1
  13. package/dist/components/Dialog.svelte +359 -356
  14. package/dist/components/Disclosure.svelte +201 -201
  15. package/dist/components/EmptyState.svelte +88 -88
  16. package/dist/components/ErrorState.svelte +135 -135
  17. package/dist/components/ImageViewer.svelte +764 -0
  18. package/dist/components/ImageViewer.svelte.d.ts +55 -0
  19. package/dist/components/KeyValueList.svelte +114 -114
  20. package/dist/components/ListDetail.svelte +218 -0
  21. package/dist/components/ListDetail.svelte.d.ts +37 -0
  22. package/dist/components/LoadRegion.svelte +219 -219
  23. package/dist/components/MediaFrame.svelte +110 -110
  24. package/dist/components/MediaImage.svelte +256 -256
  25. package/dist/components/Menu.svelte +258 -258
  26. package/dist/components/MenuCheckboxItem.svelte +119 -119
  27. package/dist/components/MenuGroup.svelte +50 -50
  28. package/dist/components/MenuItem.svelte +94 -94
  29. package/dist/components/MenuRadioGroup.svelte +62 -62
  30. package/dist/components/MenuRadioItem.svelte +110 -110
  31. package/dist/components/MenuSeparator.svelte +28 -28
  32. package/dist/components/Meter.svelte +283 -0
  33. package/dist/components/Meter.svelte.d.ts +66 -0
  34. package/dist/components/NativeSelect.svelte +18 -2
  35. package/dist/components/NativeSelect.svelte.d.ts +6 -0
  36. package/dist/components/Notice.svelte +262 -0
  37. package/dist/components/Notice.svelte.d.ts +30 -0
  38. package/dist/components/Popover.svelte +222 -222
  39. package/dist/components/Progress.svelte +157 -157
  40. package/dist/components/RadioGroup.svelte +440 -0
  41. package/dist/components/RadioGroup.svelte.d.ts +50 -0
  42. package/dist/components/Select.svelte +471 -405
  43. package/dist/components/Select.svelte.d.ts +6 -0
  44. package/dist/components/Skeleton.svelte +149 -149
  45. package/dist/components/Spinner.svelte +118 -117
  46. package/dist/components/Stat.svelte +253 -253
  47. package/dist/components/Steps.svelte +189 -189
  48. package/dist/components/Switch.svelte +222 -222
  49. package/dist/components/Table.svelte +504 -504
  50. package/dist/components/Tabs.svelte +246 -246
  51. package/dist/components/Tag.svelte +40 -40
  52. package/dist/components/TextArea.svelte +272 -0
  53. package/dist/components/TextArea.svelte.d.ts +28 -0
  54. package/dist/components/TextField.svelte +256 -256
  55. package/dist/components/Timeline.svelte +156 -156
  56. package/dist/components/Toaster.svelte +411 -411
  57. package/dist/components/Tooltip.svelte +200 -200
  58. package/dist/components/TooltipGroup.svelte +46 -46
  59. package/dist/components/internal/Scrim.svelte +52 -52
  60. package/dist/components/internal/Sheet.svelte +263 -263
  61. package/dist/components/internal/groups.d.ts +14 -0
  62. package/dist/components/internal/groups.js +23 -0
  63. package/dist/fonts.css +71 -71
  64. package/dist/index.d.ts +6 -0
  65. package/dist/index.js +6 -0
  66. package/dist/tokens.css +283 -279
  67. package/package.json +81 -76
@@ -1,222 +1,222 @@
1
- <script lang="ts" module>
2
- import { Switch as BitsSwitch } from 'bits-ui';
3
-
4
- /** Attributes and handlers not listed here go to the switch button. */
5
- export type SwitchProps = Omit<BitsSwitch.RootProps, 'child' | 'children' | 'ref'> & {
6
- /**
7
- * The setting's name, as written (never caps), at the start of the line;
8
- * the switch sits at its end. Pressing anywhere on the label turns the
9
- * switch on or off. Without it, give the switch an accessible name with
10
- * `aria-label`.
11
- */
12
- label?: string;
13
- /** A second line in `--muted` under the label, read out as the switch's description. */
14
- hint?: string;
15
- /** The switch button. */
16
- ref?: HTMLElement | null;
17
- };
18
- </script>
19
-
20
- <script lang="ts">
21
- const uid = $props.id();
22
-
23
- let {
24
- checked = $bindable(false),
25
- label,
26
- hint,
27
- id = uid,
28
- ref = $bindable(null),
29
- class: className,
30
- 'aria-describedby': describedBy,
31
- ...rest
32
- }: SwitchProps = $props();
33
-
34
- const hintId = $derived(`${id}-hint`);
35
- const describedByIds = $derived([hint ? hintId : null, describedBy].filter(Boolean).join(' ') || undefined);
36
- </script>
37
-
38
- <!--
39
- A Bits UI Switch: a <button role="switch"> with aria-checked, its state in
40
- data-state (checked, unchecked) and data-disabled. An on/off setting that
41
- applies at once, as omp-remote's settings rows: the label, the switch at
42
- the end of its line, then the hint. Attributes, handlers and `class` go to
43
- the button.
44
- -->
45
- <div class="hp-switch">
46
- {#if label}
47
- <label class="hp-dense" for={id}>{label}</label>
48
- {/if}
49
- <span class="control">
50
- <BitsSwitch.Root bind:checked bind:ref {id} aria-describedby={describedByIds} {...rest}>
51
- {#snippet child({ props })}
52
- <button {...props} class={['track', className]}>
53
- <BitsSwitch.Thumb>
54
- {#snippet child({ props: thumbProps })}
55
- <span {...thumbProps} class="thumb"></span>
56
- {/snippet}
57
- </BitsSwitch.Thumb>
58
- </button>
59
- {/snippet}
60
- </BitsSwitch.Root>
61
- </span>
62
- {#if hint}
63
- <p class="hint hp-caption" id={hintId}>{hint}</p>
64
- {/if}
65
- </div>
66
-
67
- <style>
68
- /* The label fills the line and the switch sits at its end. The first
69
- line is one hit-target band (24px fine, 44px coarse): the switch sits
70
- centred in it and the label's first line too, so the whole label line
71
- is a target. The hint runs under the label. Without a label the root
72
- is as wide as the switch. */
73
- .hp-switch {
74
- /* The label's line height, as .hp-dense sets it. */
75
- --_line: 24px;
76
- display: grid;
77
- grid-template-columns: auto;
78
- justify-content: start;
79
- align-items: start;
80
- }
81
- .hp-switch:has(> label) {
82
- grid-template-columns: minmax(0, 1fr) auto;
83
- column-gap: var(--space-4);
84
- }
85
- @media (pointer: fine) {
86
- .hp-switch {
87
- --_line: 20px;
88
- }
89
- }
90
-
91
- label {
92
- padding: calc((var(--hit-target) - var(--_line)) / 2) 0;
93
- cursor: pointer;
94
- -webkit-tap-highlight-color: transparent;
95
- }
96
-
97
- .control {
98
- position: relative;
99
- grid-column: -2;
100
- grid-row: 1;
101
- display: flex;
102
- align-items: center;
103
- height: var(--hit-target);
104
- }
105
-
106
- /* A black box with a 3:1 boundary and a square thumb. On, the edge and the
107
- thumb turn titanium and the thumb shows at the end; the box stays black,
108
- because selection is never a fill. Focus is base.css's contour 4px
109
- outside, so it never looks like the on edge. */
110
- .track {
111
- position: relative;
112
- display: block;
113
- box-sizing: border-box;
114
- width: 40px;
115
- height: 24px;
116
- margin: 0;
117
- padding: 0;
118
- border: 1px solid var(--border-control);
119
- background: var(--canvas);
120
- cursor: pointer;
121
- -webkit-tap-highlight-color: transparent;
122
- }
123
- /* The hit area: at least --hit-target square, centred on the track. */
124
- .track::before {
125
- content: '';
126
- position: absolute;
127
- top: 50%;
128
- left: 50%;
129
- width: max(100%, var(--hit-target));
130
- height: max(100%, var(--hit-target));
131
- translate: -50% -50%;
132
- }
133
- .track[data-state='checked'] {
134
- border-color: var(--accent);
135
- }
136
-
137
- /* The thumb: two 16px squares, 4px in from the outer edge (inside the
138
- 1px border), ::before at the start (off) and ::after at the end (on).
139
- Each is at opacity 0 until its state comes. The one a change brings
140
- fades in from 0 at its place over --dur-mark (BRIEF, short motion) and
141
- the other goes at once, so the thumb never slides. A CSS transition
142
- never runs on an element's first style, so a switch shows its state at
143
- once when it renders. 0ms is a snap. Opacity only: nothing moves, so
144
- reduced motion keeps it. */
145
- .thumb {
146
- position: absolute;
147
- top: calc(var(--space-1) - 1px);
148
- left: calc(var(--space-1) - 1px);
149
- width: 16px;
150
- height: 16px;
151
- }
152
- .thumb::before,
153
- .thumb::after {
154
- content: '';
155
- position: absolute;
156
- top: 0;
157
- width: 16px;
158
- height: 16px;
159
- opacity: 0;
160
- }
161
- .thumb::before {
162
- left: 0;
163
- background: var(--muted);
164
- }
165
- .thumb::after {
166
- left: 16px;
167
- background: var(--accent);
168
- }
169
- .track[data-state='unchecked'] .thumb::before,
170
- .track[data-state='checked'] .thumb::after {
171
- opacity: 1;
172
- transition: opacity var(--dur-mark) var(--settle);
173
- }
174
-
175
- .hint {
176
- grid-column: 1;
177
- color: var(--muted);
178
- }
179
-
180
- /* ---- Hover: fine pointers only, over the switch or its label ------- */
181
-
182
- @media (hover: hover) and (pointer: fine) {
183
- .track {
184
- transition:
185
- background-color var(--dur-hover) var(--settle),
186
- border-color var(--dur-hover) var(--settle);
187
- }
188
- .hp-switch:has(> label:hover, .track:hover) .track:not(:disabled) {
189
- background-color: var(--surface-hover);
190
- }
191
- .hp-switch:has(> label:hover, .track:hover) .track[data-state='unchecked']:not(:disabled) {
192
- border-color: var(--muted);
193
- }
194
- .hp-switch:has(> label:active, .track:active) .track:not(:disabled) {
195
- transition-duration: var(--dur-press);
196
- }
197
- }
198
-
199
- /* ---- Press: one step past hover, so it reads on a phone too -------- */
200
-
201
- .hp-switch:has(> label:active, .track:active) .track:not(:disabled) {
202
- background-color: var(--surface-raised);
203
- }
204
-
205
- /* ---- Disabled: the quieter --border and a --border thumb, as
206
- omp-remote's; on keeps its place at the end ------------------------ */
207
-
208
- .track:disabled {
209
- border-color: var(--border);
210
- cursor: not-allowed;
211
- }
212
- .track:disabled .thumb::before {
213
- background: var(--border);
214
- }
215
- .track:disabled .thumb::after {
216
- background: var(--muted);
217
- }
218
- .hp-switch:has(.track:disabled) label {
219
- color: var(--muted);
220
- cursor: not-allowed;
221
- }
222
- </style>
1
+ <script lang="ts" module>
2
+ import { Switch as BitsSwitch } from 'bits-ui';
3
+
4
+ /** Attributes and handlers not listed here go to the switch button. */
5
+ export type SwitchProps = Omit<BitsSwitch.RootProps, 'child' | 'children' | 'ref'> & {
6
+ /**
7
+ * The setting's name, as written (never caps), at the start of the line;
8
+ * the switch sits at its end. Pressing anywhere on the label turns the
9
+ * switch on or off. Without it, give the switch an accessible name with
10
+ * `aria-label`.
11
+ */
12
+ label?: string;
13
+ /** A second line in `--muted` under the label, read out as the switch's description. */
14
+ hint?: string;
15
+ /** The switch button. */
16
+ ref?: HTMLElement | null;
17
+ };
18
+ </script>
19
+
20
+ <script lang="ts">
21
+ const uid = $props.id();
22
+
23
+ let {
24
+ checked = $bindable(false),
25
+ label,
26
+ hint,
27
+ id = uid,
28
+ ref = $bindable(null),
29
+ class: className,
30
+ 'aria-describedby': describedBy,
31
+ ...rest
32
+ }: SwitchProps = $props();
33
+
34
+ const hintId = $derived(`${id}-hint`);
35
+ const describedByIds = $derived([hint ? hintId : null, describedBy].filter(Boolean).join(' ') || undefined);
36
+ </script>
37
+
38
+ <!--
39
+ A Bits UI Switch: a <button role="switch"> with aria-checked, its state in
40
+ data-state (checked, unchecked) and data-disabled. An on/off setting that
41
+ applies at once, as omp-remote's settings rows: the label, the switch at
42
+ the end of its line, then the hint. Attributes, handlers and `class` go to
43
+ the button.
44
+ -->
45
+ <div class="hp-switch">
46
+ {#if label}
47
+ <label class="hp-dense" for={id}>{label}</label>
48
+ {/if}
49
+ <span class="control">
50
+ <BitsSwitch.Root bind:checked bind:ref {id} aria-describedby={describedByIds} {...rest}>
51
+ {#snippet child({ props })}
52
+ <button {...props} class={['track', className]}>
53
+ <BitsSwitch.Thumb>
54
+ {#snippet child({ props: thumbProps })}
55
+ <span {...thumbProps} class="thumb"></span>
56
+ {/snippet}
57
+ </BitsSwitch.Thumb>
58
+ </button>
59
+ {/snippet}
60
+ </BitsSwitch.Root>
61
+ </span>
62
+ {#if hint}
63
+ <p class="hint hp-caption" id={hintId}>{hint}</p>
64
+ {/if}
65
+ </div>
66
+
67
+ <style>
68
+ /* The label fills the line and the switch sits at its end. The first
69
+ line is one hit-target band (24px fine, 44px coarse): the switch sits
70
+ centred in it and the label's first line too, so the whole label line
71
+ is a target. The hint runs under the label. Without a label the root
72
+ is as wide as the switch. */
73
+ .hp-switch {
74
+ /* The label's line height, as .hp-dense sets it. */
75
+ --_line: 24px;
76
+ display: grid;
77
+ grid-template-columns: auto;
78
+ justify-content: start;
79
+ align-items: start;
80
+ }
81
+ .hp-switch:has(> label) {
82
+ grid-template-columns: minmax(0, 1fr) auto;
83
+ column-gap: var(--space-4);
84
+ }
85
+ @media (pointer: fine) {
86
+ .hp-switch {
87
+ --_line: 20px;
88
+ }
89
+ }
90
+
91
+ label {
92
+ padding: calc((var(--hit-target) - var(--_line)) / 2) 0;
93
+ cursor: pointer;
94
+ -webkit-tap-highlight-color: transparent;
95
+ }
96
+
97
+ .control {
98
+ position: relative;
99
+ grid-column: -2;
100
+ grid-row: 1;
101
+ display: flex;
102
+ align-items: center;
103
+ height: var(--hit-target);
104
+ }
105
+
106
+ /* A black box with a 3:1 boundary and a square thumb. On, the edge and the
107
+ thumb turn titanium and the thumb shows at the end; the box stays black,
108
+ because selection is never a fill. Focus is base.css's contour 4px
109
+ outside, so it never looks like the on edge. */
110
+ .track {
111
+ position: relative;
112
+ display: block;
113
+ box-sizing: border-box;
114
+ width: 40px;
115
+ height: 24px;
116
+ margin: 0;
117
+ padding: 0;
118
+ border: 1px solid var(--border-control);
119
+ background: var(--canvas);
120
+ cursor: pointer;
121
+ -webkit-tap-highlight-color: transparent;
122
+ }
123
+ /* The hit area: at least --hit-target square, centred on the track. */
124
+ .track::before {
125
+ content: '';
126
+ position: absolute;
127
+ top: 50%;
128
+ left: 50%;
129
+ width: max(100%, var(--hit-target));
130
+ height: max(100%, var(--hit-target));
131
+ translate: -50% -50%;
132
+ }
133
+ .track[data-state='checked'] {
134
+ border-color: var(--accent);
135
+ }
136
+
137
+ /* The thumb: two 16px squares, 4px in from the outer edge (inside the
138
+ 1px border), ::before at the start (off) and ::after at the end (on).
139
+ Each is at opacity 0 until its state comes. The one a change brings
140
+ fades in from 0 at its place over --dur-mark (BRIEF, short motion) and
141
+ the other goes at once, so the thumb never slides. A CSS transition
142
+ never runs on an element's first style, so a switch shows its state at
143
+ once when it renders. 0ms is a snap. Opacity only: nothing moves, so
144
+ reduced motion keeps it. */
145
+ .thumb {
146
+ position: absolute;
147
+ top: calc(var(--space-1) - 1px);
148
+ left: calc(var(--space-1) - 1px);
149
+ width: 16px;
150
+ height: 16px;
151
+ }
152
+ .thumb::before,
153
+ .thumb::after {
154
+ content: '';
155
+ position: absolute;
156
+ top: 0;
157
+ width: 16px;
158
+ height: 16px;
159
+ opacity: 0;
160
+ }
161
+ .thumb::before {
162
+ left: 0;
163
+ background: var(--muted);
164
+ }
165
+ .thumb::after {
166
+ left: 16px;
167
+ background: var(--accent);
168
+ }
169
+ .track[data-state='unchecked'] .thumb::before,
170
+ .track[data-state='checked'] .thumb::after {
171
+ opacity: 1;
172
+ transition: opacity var(--dur-mark) var(--settle);
173
+ }
174
+
175
+ .hint {
176
+ grid-column: 1;
177
+ color: var(--muted);
178
+ }
179
+
180
+ /* ---- Hover: fine pointers only, over the switch or its label ------- */
181
+
182
+ @media (hover: hover) and (pointer: fine) {
183
+ .track {
184
+ transition:
185
+ background-color var(--dur-hover) var(--settle),
186
+ border-color var(--dur-hover) var(--settle);
187
+ }
188
+ .hp-switch:has(> label:hover, .track:hover) .track:not(:disabled) {
189
+ background-color: var(--surface-hover);
190
+ }
191
+ .hp-switch:has(> label:hover, .track:hover) .track[data-state='unchecked']:not(:disabled) {
192
+ border-color: var(--muted);
193
+ }
194
+ .hp-switch:has(> label:active, .track:active) .track:not(:disabled) {
195
+ transition-duration: var(--dur-press);
196
+ }
197
+ }
198
+
199
+ /* ---- Press: one step past hover, so it reads on a phone too -------- */
200
+
201
+ .hp-switch:has(> label:active, .track:active) .track:not(:disabled) {
202
+ background-color: var(--surface-raised);
203
+ }
204
+
205
+ /* ---- Disabled: the quieter --border and a --border thumb, as
206
+ omp-remote's; on keeps its place at the end ------------------------ */
207
+
208
+ .track:disabled {
209
+ border-color: var(--border);
210
+ cursor: not-allowed;
211
+ }
212
+ .track:disabled .thumb::before {
213
+ background: var(--border);
214
+ }
215
+ .track:disabled .thumb::after {
216
+ background: var(--muted);
217
+ }
218
+ .hp-switch:has(.track:disabled) label {
219
+ color: var(--muted);
220
+ cursor: not-allowed;
221
+ }
222
+ </style>