@mystravil/hardpoint 0.2.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 (52) hide show
  1. package/CHANGELOG.md +42 -38
  2. package/LICENSE +25 -25
  3. package/README.md +67 -64
  4. package/dist/base.css +625 -625
  5. package/dist/components/AppShell.svelte +698 -698
  6. package/dist/components/Button.svelte +174 -174
  7. package/dist/components/Checkbox.svelte +235 -235
  8. package/dist/components/CheckboxGroup.svelte +207 -207
  9. package/dist/components/Combobox.svelte +901 -901
  10. package/dist/components/Dialog.svelte +359 -359
  11. package/dist/components/Disclosure.svelte +201 -201
  12. package/dist/components/EmptyState.svelte +88 -88
  13. package/dist/components/ErrorState.svelte +135 -135
  14. package/dist/components/ImageViewer.svelte +764 -764
  15. package/dist/components/KeyValueList.svelte +114 -114
  16. package/dist/components/ListDetail.svelte +218 -218
  17. package/dist/components/LoadRegion.svelte +219 -219
  18. package/dist/components/MediaFrame.svelte +110 -110
  19. package/dist/components/MediaImage.svelte +256 -256
  20. package/dist/components/Menu.svelte +258 -258
  21. package/dist/components/MenuCheckboxItem.svelte +119 -119
  22. package/dist/components/MenuGroup.svelte +50 -50
  23. package/dist/components/MenuItem.svelte +94 -94
  24. package/dist/components/MenuRadioGroup.svelte +62 -62
  25. package/dist/components/MenuRadioItem.svelte +110 -110
  26. package/dist/components/MenuSeparator.svelte +28 -28
  27. package/dist/components/Meter.svelte +283 -283
  28. package/dist/components/NativeSelect.svelte +135 -135
  29. package/dist/components/Notice.svelte +262 -262
  30. package/dist/components/Popover.svelte +222 -222
  31. package/dist/components/Progress.svelte +157 -157
  32. package/dist/components/RadioGroup.svelte +440 -440
  33. package/dist/components/Select.svelte +471 -471
  34. package/dist/components/Skeleton.svelte +149 -149
  35. package/dist/components/Spinner.svelte +118 -118
  36. package/dist/components/Stat.svelte +253 -253
  37. package/dist/components/Steps.svelte +189 -189
  38. package/dist/components/Switch.svelte +222 -222
  39. package/dist/components/Table.svelte +504 -504
  40. package/dist/components/Tabs.svelte +246 -246
  41. package/dist/components/Tag.svelte +40 -40
  42. package/dist/components/TextArea.svelte +272 -272
  43. package/dist/components/TextField.svelte +256 -256
  44. package/dist/components/Timeline.svelte +156 -156
  45. package/dist/components/Toaster.svelte +411 -411
  46. package/dist/components/Tooltip.svelte +200 -200
  47. package/dist/components/TooltipGroup.svelte +46 -46
  48. package/dist/components/internal/Scrim.svelte +52 -52
  49. package/dist/components/internal/Sheet.svelte +263 -263
  50. package/dist/fonts.css +71 -71
  51. package/dist/tokens.css +283 -283
  52. 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>