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