@mystravil/hardpoint 0.2.0 → 0.3.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.
- package/CHANGELOG.md +51 -38
- package/LICENSE +25 -25
- package/README.md +67 -64
- package/dist/base.css +625 -625
- package/dist/components/AppShell.svelte +698 -698
- package/dist/components/Button.svelte +221 -174
- package/dist/components/Button.svelte.d.ts +18 -2
- package/dist/components/Checkbox.svelte +235 -235
- package/dist/components/CheckboxGroup.svelte +207 -207
- package/dist/components/Combobox.svelte +901 -901
- package/dist/components/Dialog.svelte +359 -359
- 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 -764
- package/dist/components/KeyValueList.svelte +114 -114
- package/dist/components/ListDetail.svelte +218 -218
- 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 +275 -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 -283
- package/dist/components/NativeSelect.svelte +135 -135
- package/dist/components/Notice.svelte +262 -262
- package/dist/components/Popover.svelte +222 -222
- package/dist/components/Progress.svelte +157 -157
- package/dist/components/RadioGroup.svelte +440 -440
- package/dist/components/Select.svelte +471 -471
- package/dist/components/Skeleton.svelte +149 -149
- package/dist/components/Spinner.svelte +118 -118
- 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 -272
- package/dist/components/TextField.svelte +396 -256
- package/dist/components/TextField.svelte.d.ts +16 -1
- 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/fonts.css +71 -71
- package/dist/tokens.css +283 -283
- package/package.json +81 -76
|
@@ -1,174 +1,221 @@
|
|
|
1
|
-
<script lang="ts" module>
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
*
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
opens
|
|
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
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
/*
|
|
151
|
-
|
|
152
|
-
:global(.hp-button[data-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
1
|
+
<script lang="ts" module>
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
|
4
|
+
|
|
5
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'tertiary';
|
|
6
|
+
|
|
7
|
+
type ButtonOwnProps = {
|
|
8
|
+
/**
|
|
9
|
+
* `primary`: solid titanium block, for the view's one group of solid
|
|
10
|
+
* blocks. `secondary` (default): outlined. `tertiary`: caps label only.
|
|
11
|
+
*/
|
|
12
|
+
variant?: ButtonVariant;
|
|
13
|
+
/** Ends the label in a small ▸: the button opens another view. */
|
|
14
|
+
opens?: boolean;
|
|
15
|
+
/**
|
|
16
|
+
* A square, icon-only button (height and width are `--control-height`).
|
|
17
|
+
* It has no visible label, so it needs an accessible name: pass
|
|
18
|
+
* `aria-label`.
|
|
19
|
+
*/
|
|
20
|
+
icon?: boolean;
|
|
21
|
+
/** The `<button>`, or the `<a>` when `href` is set. */
|
|
22
|
+
ref?: HTMLElement | null;
|
|
23
|
+
children?: Snippet;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* An `<a>` when `href` is set, a `<button>` otherwise. Attributes and
|
|
28
|
+
* handlers not listed here go to the element.
|
|
29
|
+
*/
|
|
30
|
+
export type ButtonProps =
|
|
31
|
+
| (ButtonOwnProps &
|
|
32
|
+
Omit<HTMLButtonAttributes, 'children' | 'type' | 'href'> & {
|
|
33
|
+
type?: HTMLButtonAttributes['type'];
|
|
34
|
+
href?: never;
|
|
35
|
+
})
|
|
36
|
+
| (ButtonOwnProps &
|
|
37
|
+
Omit<HTMLAnchorAttributes, 'children' | 'type' | 'href'> & {
|
|
38
|
+
href: HTMLAnchorAttributes['href'];
|
|
39
|
+
type?: never;
|
|
40
|
+
disabled?: HTMLButtonAttributes['disabled'];
|
|
41
|
+
});
|
|
42
|
+
</script>
|
|
43
|
+
|
|
44
|
+
<script lang="ts">
|
|
45
|
+
let {
|
|
46
|
+
variant = 'secondary',
|
|
47
|
+
opens = false,
|
|
48
|
+
icon = false,
|
|
49
|
+
class: className,
|
|
50
|
+
ref = $bindable(null),
|
|
51
|
+
href,
|
|
52
|
+
disabled,
|
|
53
|
+
children,
|
|
54
|
+
...rest
|
|
55
|
+
}: ButtonProps = $props();
|
|
56
|
+
|
|
57
|
+
// `rest` holds one element's attributes; each branch reads it as its own.
|
|
58
|
+
const asButton = (attributes: typeof rest) => attributes as HTMLButtonAttributes;
|
|
59
|
+
const asLink = (attributes: typeof rest) => attributes as HTMLAnchorAttributes;
|
|
60
|
+
</script>
|
|
61
|
+
|
|
62
|
+
<!--
|
|
63
|
+
A plain <button> without `href`, an <a> with it, with no component layer
|
|
64
|
+
between: a transcript may draw hundreds. A disabled link renders without
|
|
65
|
+
href, with role="link", aria-disabled="true" and tabindex -1; a disabled
|
|
66
|
+
<button> is not focusable.
|
|
67
|
+
-->
|
|
68
|
+
{#if !href}
|
|
69
|
+
<button
|
|
70
|
+
bind:this={ref}
|
|
71
|
+
class={['hp-button', 'hp-label', className]}
|
|
72
|
+
data-variant={variant}
|
|
73
|
+
data-opens={opens || undefined}
|
|
74
|
+
data-icon={icon || undefined}
|
|
75
|
+
{disabled}
|
|
76
|
+
{...asButton(rest)}
|
|
77
|
+
>
|
|
78
|
+
{@render children?.()}
|
|
79
|
+
</button>
|
|
80
|
+
{:else}
|
|
81
|
+
<a
|
|
82
|
+
bind:this={ref}
|
|
83
|
+
class={['hp-button', 'hp-label', className]}
|
|
84
|
+
data-variant={variant}
|
|
85
|
+
data-opens={opens || undefined}
|
|
86
|
+
data-icon={icon || undefined}
|
|
87
|
+
href={disabled ? undefined : href}
|
|
88
|
+
role={disabled ? 'link' : undefined}
|
|
89
|
+
aria-disabled={disabled ? 'true' : undefined}
|
|
90
|
+
tabindex={disabled ? -1 : undefined}
|
|
91
|
+
{...asLink(rest)}
|
|
92
|
+
>
|
|
93
|
+
{@render children?.()}
|
|
94
|
+
</a>
|
|
95
|
+
{/if}
|
|
96
|
+
|
|
97
|
+
<style>
|
|
98
|
+
/* Global rules keyed on .hp-button and its data-*, at one class of
|
|
99
|
+
specificity as when Bits UI rendered the element, so an app's rules
|
|
100
|
+
that override them still apply. */
|
|
101
|
+
:global(.hp-button) {
|
|
102
|
+
display: inline-flex;
|
|
103
|
+
align-items: center;
|
|
104
|
+
justify-content: space-between;
|
|
105
|
+
gap: var(--space-4);
|
|
106
|
+
box-sizing: border-box;
|
|
107
|
+
height: var(--control-height);
|
|
108
|
+
/* The visible box is the hit area: 36px fine, 44px coarse, and never
|
|
109
|
+
narrower than --hit-target for a short label. */
|
|
110
|
+
min-width: var(--hit-target);
|
|
111
|
+
padding: 0 var(--space-3);
|
|
112
|
+
border: 0;
|
|
113
|
+
background: transparent;
|
|
114
|
+
color: var(--text);
|
|
115
|
+
font-family: var(--sans);
|
|
116
|
+
text-decoration: none;
|
|
117
|
+
white-space: nowrap;
|
|
118
|
+
cursor: pointer;
|
|
119
|
+
-webkit-tap-highlight-color: transparent;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/* ---- Variants ---------------------------------------------------- */
|
|
123
|
+
|
|
124
|
+
/* Solid titanium block with a black label. */
|
|
125
|
+
:global(.hp-button[data-variant='primary']) {
|
|
126
|
+
background: var(--accent);
|
|
127
|
+
color: var(--canvas);
|
|
128
|
+
}
|
|
129
|
+
/* Outlined: a 3:1 boundary, titanium label, black fill. */
|
|
130
|
+
:global(.hp-button[data-variant='secondary']) {
|
|
131
|
+
border: 1px solid var(--border-control);
|
|
132
|
+
background: var(--canvas);
|
|
133
|
+
}
|
|
134
|
+
/* The label alone. */
|
|
135
|
+
:global(.hp-button[data-variant='tertiary']) {
|
|
136
|
+
background: transparent;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/* ---- Opens another view: a small ▸ drawn in CSS ------------------ */
|
|
140
|
+
|
|
141
|
+
:global(.hp-button[data-opens]::after) {
|
|
142
|
+
content: '';
|
|
143
|
+
flex: none;
|
|
144
|
+
width: 6px;
|
|
145
|
+
height: 8px;
|
|
146
|
+
background: currentColor;
|
|
147
|
+
clip-path: polygon(0 0, 100% 50%, 0 100%);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/* ---- Icon only: a square ----------------------------------------- */
|
|
151
|
+
|
|
152
|
+
:global(.hp-button[data-icon]) {
|
|
153
|
+
justify-content: center;
|
|
154
|
+
width: var(--control-height);
|
|
155
|
+
padding: 0;
|
|
156
|
+
}
|
|
157
|
+
/* The icon is the consumer's inline <svg>; it draws in currentColor. */
|
|
158
|
+
:global(.hp-button svg) {
|
|
159
|
+
flex: none;
|
|
160
|
+
}
|
|
161
|
+
:global(.hp-button[data-icon] svg) {
|
|
162
|
+
width: var(--space-4);
|
|
163
|
+
height: var(--space-4);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/* ---- Hover: fine pointers only ----------------------------------- */
|
|
167
|
+
|
|
168
|
+
@media (hover: hover) and (pointer: fine) {
|
|
169
|
+
:global(.hp-button) {
|
|
170
|
+
transition:
|
|
171
|
+
background-color var(--dur-hover) var(--settle),
|
|
172
|
+
color var(--dur-hover) var(--settle);
|
|
173
|
+
}
|
|
174
|
+
:global(.hp-button:active:not(:disabled):not([aria-disabled='true'])) {
|
|
175
|
+
transition-duration: var(--dur-press);
|
|
176
|
+
}
|
|
177
|
+
:global(.hp-button[data-variant='primary']:hover:not(:disabled):not([aria-disabled='true'])) {
|
|
178
|
+
background: var(--muted);
|
|
179
|
+
}
|
|
180
|
+
:global(.hp-button[data-variant='secondary']:hover:not(:disabled):not([aria-disabled='true'])),
|
|
181
|
+
:global(.hp-button[data-variant='tertiary']:hover:not(:disabled):not([aria-disabled='true'])) {
|
|
182
|
+
background: var(--surface-hover);
|
|
183
|
+
}
|
|
184
|
+
/* The tint alone barely shows (1.03:1), so the label also underlines. */
|
|
185
|
+
:global(.hp-button[data-variant='tertiary']:hover:not(:disabled):not([aria-disabled='true'])) {
|
|
186
|
+
text-decoration: underline;
|
|
187
|
+
text-decoration-thickness: 1px;
|
|
188
|
+
text-underline-offset: 0.3em;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/* ---- Press: after hover, so it wins while the pointer is down ----- */
|
|
193
|
+
|
|
194
|
+
:global(.hp-button[data-variant='primary']:active:not(:disabled):not([aria-disabled='true'])) {
|
|
195
|
+
background: var(--muted);
|
|
196
|
+
}
|
|
197
|
+
/* One step past the hover tint, so a press reads on a phone too. */
|
|
198
|
+
:global(.hp-button[data-variant='secondary']:active:not(:disabled):not([aria-disabled='true'])),
|
|
199
|
+
:global(.hp-button[data-variant='tertiary']:active:not(:disabled):not([aria-disabled='true'])) {
|
|
200
|
+
background: var(--surface-raised);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* ---- Disabled: muted ink. A <button> is not focusable; a link has
|
|
204
|
+
no href. -------------------------------------------------------- */
|
|
205
|
+
|
|
206
|
+
:global(.hp-button:disabled),
|
|
207
|
+
:global(.hp-button[aria-disabled='true']) {
|
|
208
|
+
color: var(--muted);
|
|
209
|
+
cursor: not-allowed;
|
|
210
|
+
}
|
|
211
|
+
:global(.hp-button[data-variant='primary']:disabled),
|
|
212
|
+
:global(.hp-button[data-variant='primary'][aria-disabled='true']) {
|
|
213
|
+
/* --muted is 4.9:1 on the band. */
|
|
214
|
+
background: var(--surface-band);
|
|
215
|
+
}
|
|
216
|
+
:global(.hp-button[data-variant='secondary']:disabled),
|
|
217
|
+
:global(.hp-button[data-variant='secondary'][aria-disabled='true']) {
|
|
218
|
+
/* An off control needs no 3:1 boundary. */
|
|
219
|
+
border-color: var(--border);
|
|
220
|
+
}
|
|
221
|
+
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
|
|
2
3
|
export type ButtonVariant = 'primary' | 'secondary' | 'tertiary';
|
|
3
|
-
|
|
4
|
+
type ButtonOwnProps = {
|
|
4
5
|
/**
|
|
5
6
|
* `primary`: solid titanium block, for the view's one group of solid
|
|
6
7
|
* blocks. `secondary` (default): outlined. `tertiary`: caps label only.
|
|
@@ -14,7 +15,22 @@ export type ButtonProps = BitsButton.RootProps & {
|
|
|
14
15
|
* `aria-label`.
|
|
15
16
|
*/
|
|
16
17
|
icon?: boolean;
|
|
18
|
+
/** The `<button>`, or the `<a>` when `href` is set. */
|
|
19
|
+
ref?: HTMLElement | null;
|
|
20
|
+
children?: Snippet;
|
|
17
21
|
};
|
|
22
|
+
/**
|
|
23
|
+
* An `<a>` when `href` is set, a `<button>` otherwise. Attributes and
|
|
24
|
+
* handlers not listed here go to the element.
|
|
25
|
+
*/
|
|
26
|
+
export type ButtonProps = (ButtonOwnProps & Omit<HTMLButtonAttributes, 'children' | 'type' | 'href'> & {
|
|
27
|
+
type?: HTMLButtonAttributes['type'];
|
|
28
|
+
href?: never;
|
|
29
|
+
}) | (ButtonOwnProps & Omit<HTMLAnchorAttributes, 'children' | 'type' | 'href'> & {
|
|
30
|
+
href: HTMLAnchorAttributes['href'];
|
|
31
|
+
type?: never;
|
|
32
|
+
disabled?: HTMLButtonAttributes['disabled'];
|
|
33
|
+
});
|
|
18
34
|
declare const Button: import("svelte").Component<ButtonProps, {}, "ref">;
|
|
19
35
|
type Button = ReturnType<typeof Button>;
|
|
20
36
|
export default Button;
|