@thomasfosterau/components 0.1.0 → 0.2.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/README.md +241 -56
- package/dist/canvas/VectorCanvas.svelte +89 -8
- package/dist/canvas/VectorCanvas.svelte.d.ts +19 -1
- package/dist/canvas/types.d.ts +1 -1
- package/dist/charts/types.d.ts +1 -1
- package/dist/citations/list-format.js +3 -1
- package/dist/data/ChatBubble.svelte +48 -0
- package/dist/data/ChatBubble.svelte.d.ts +33 -0
- package/dist/data/DescriptionList.svelte +9 -3
- package/dist/data/DescriptionList.svelte.d.ts +1 -1
- package/dist/data/DescriptionRow.svelte +6 -5
- package/dist/data/MessageThread.svelte +29 -0
- package/dist/data/MessageThread.svelte.d.ts +17 -0
- package/dist/data/Pagination.svelte +5 -5
- package/dist/data/Pagination.svelte.d.ts +8 -0
- package/dist/data/PaginationFooter.svelte +2 -1
- package/dist/data/PaginationFooter.svelte.d.ts +2 -0
- package/dist/data/Table.svelte +9 -3
- package/dist/data/description-context.d.ts +12 -6
- package/dist/data/description-context.js +6 -5
- package/dist/data/index.d.ts +2 -0
- package/dist/data/index.js +2 -0
- package/dist/data/table-types.d.ts +7 -0
- package/dist/feedback/Dialog.svelte +19 -49
- package/dist/feedback/Dialog.svelte.d.ts +0 -1
- package/dist/feedback/DialogFrame.svelte +64 -0
- package/dist/feedback/DialogFrame.svelte.d.ts +23 -0
- package/dist/feedback/Drawer.svelte +43 -0
- package/dist/feedback/Drawer.svelte.d.ts +43 -0
- package/dist/feedback/SegmentBar.svelte.d.ts +1 -0
- package/dist/feedback/StatTile.svelte.d.ts +1 -0
- package/dist/feedback/Steps.svelte +72 -0
- package/dist/feedback/Steps.svelte.d.ts +61 -0
- package/dist/feedback/Timeline.svelte.d.ts +3 -0
- package/dist/feedback/index.d.ts +3 -0
- package/dist/feedback/index.js +2 -0
- package/dist/feedback/sizes.d.ts +14 -0
- package/dist/feedback/sizes.js +28 -0
- package/dist/fields/Calendar.svelte +60 -0
- package/dist/fields/Calendar.svelte.d.ts +11 -0
- package/dist/fields/CalendarMonths.svelte +86 -0
- package/dist/fields/CalendarMonths.svelte.d.ts +30 -0
- package/dist/fields/Checkbox.svelte +1 -1
- package/dist/fields/Checkbox.svelte.d.ts +6 -0
- package/dist/fields/Combobox.svelte +61 -54
- package/dist/fields/Combobox.svelte.d.ts +38 -3
- package/dist/fields/DateField.svelte +37 -0
- package/dist/fields/DateField.svelte.d.ts +20 -0
- package/dist/fields/DateInput.svelte +1 -1
- package/dist/fields/DateInput.svelte.d.ts +6 -0
- package/dist/fields/DatePicker.svelte +47 -0
- package/dist/fields/DatePicker.svelte.d.ts +25 -0
- package/dist/fields/DateRangePicker.svelte +70 -0
- package/dist/fields/DateRangePicker.svelte.d.ts +43 -0
- package/dist/fields/Dropzone.svelte +232 -0
- package/dist/fields/Dropzone.svelte.d.ts +103 -0
- package/dist/fields/Fieldset.svelte +7 -2
- package/dist/fields/Fieldset.svelte.d.ts +3 -2
- package/dist/fields/FileInput.svelte +3 -2
- package/dist/fields/FileInput.svelte.d.ts +6 -0
- package/dist/fields/FormField.svelte +27 -3
- package/dist/fields/ImageInput.svelte.d.ts +6 -0
- package/dist/fields/MultiSelect.svelte +112 -0
- package/dist/fields/MultiSelect.svelte.d.ts +75 -0
- package/dist/fields/NumberField.svelte +190 -0
- package/dist/fields/NumberField.svelte.d.ts +76 -0
- package/dist/fields/PasswordInput.svelte +95 -0
- package/dist/fields/PasswordInput.svelte.d.ts +58 -0
- package/dist/fields/PickerPopover.svelte +47 -0
- package/dist/fields/PickerPopover.svelte.d.ts +16 -0
- package/dist/fields/PinInput.svelte +83 -0
- package/dist/fields/PinInput.svelte.d.ts +66 -0
- package/dist/fields/RadioGroup.svelte +3 -0
- package/dist/fields/RangeCalendar.svelte +51 -0
- package/dist/fields/RangeCalendar.svelte.d.ts +23 -0
- package/dist/fields/Rating.svelte +127 -0
- package/dist/fields/Rating.svelte.d.ts +86 -0
- package/dist/fields/SearchInput.svelte +2 -1
- package/dist/fields/SegmentGroup.svelte +91 -0
- package/dist/fields/SegmentGroup.svelte.d.ts +20 -0
- package/dist/fields/Select.svelte +1 -1
- package/dist/fields/Select.svelte.d.ts +6 -0
- package/dist/fields/Slider.svelte +194 -0
- package/dist/fields/Slider.svelte.d.ts +100 -0
- package/dist/fields/TagsInput.svelte +256 -0
- package/dist/fields/TagsInput.svelte.d.ts +102 -0
- package/dist/fields/TextInput.svelte +1 -1
- package/dist/fields/TextInput.svelte.d.ts +6 -0
- package/dist/fields/Textarea.svelte +1 -1
- package/dist/fields/Textarea.svelte.d.ts +6 -0
- package/dist/fields/TimeField.svelte +30 -0
- package/dist/fields/TimeField.svelte.d.ts +19 -0
- package/dist/fields/Toggle.svelte +1 -1
- package/dist/fields/Toggle.svelte.d.ts +6 -0
- package/dist/fields/VideoInput.svelte.d.ts +6 -0
- package/dist/fields/calendar-props.d.ts +119 -0
- package/dist/fields/calendar-props.js +51 -0
- package/dist/fields/dates.d.ts +28 -0
- package/dist/fields/dates.js +26 -0
- package/dist/fields/field-types.d.ts +29 -0
- package/dist/fields/field-types.js +32 -0
- package/dist/fields/file-validation.d.ts +30 -0
- package/dist/fields/file-validation.js +51 -0
- package/dist/fields/index.d.ts +9 -0
- package/dist/fields/index.js +8 -0
- package/dist/fields/latest-search.svelte.d.ts +38 -0
- package/dist/fields/latest-search.svelte.js +85 -0
- package/dist/fields/number-format.d.ts +52 -0
- package/dist/fields/number-format.js +89 -0
- package/dist/fields/segmented-field.d.ts +128 -0
- package/dist/fields/segmented-field.js +52 -0
- package/dist/fields/slider-keys.d.ts +21 -0
- package/dist/fields/slider-keys.js +37 -0
- package/dist/formatting/Countdown.svelte +110 -0
- package/dist/formatting/Countdown.svelte.d.ts +35 -0
- package/dist/formatting/Duration.svelte +18 -0
- package/dist/formatting/Duration.svelte.d.ts +20 -0
- package/dist/formatting/Highlight.svelte +4 -0
- package/dist/formatting/Highlight.svelte.d.ts +4 -0
- package/dist/formatting/duration.d.ts +44 -0
- package/dist/formatting/duration.js +125 -0
- package/dist/formatting/index.d.ts +3 -0
- package/dist/formatting/index.js +3 -0
- package/dist/forms/EntityForm.svelte +53 -45
- package/dist/forms/EntityForm.svelte.d.ts +12 -3
- package/dist/hotkeys/index.d.ts +5 -0
- package/dist/hotkeys/index.js +5 -0
- package/dist/hotkeys/match.js +12 -10
- package/dist/hotkeys/types.d.ts +4 -2
- package/dist/index.d.ts +2 -1
- package/dist/index.js +2 -1
- package/dist/infobox/Infobox.svelte +2 -2
- package/dist/infobox/Infobox.svelte.d.ts +7 -0
- package/dist/infobox/InfoboxHeader.svelte +15 -7
- package/dist/infobox/InfoboxHeader.svelte.d.ts +7 -0
- package/dist/infobox/types.d.ts +5 -5
- package/dist/layout/AppShell.svelte +50 -0
- package/dist/layout/AppShell.svelte.d.ts +28 -0
- package/dist/layout/Cluster.svelte +28 -0
- package/dist/layout/Cluster.svelte.d.ts +27 -0
- package/dist/layout/Fits.svelte +27 -0
- package/dist/layout/Fits.svelte.d.ts +13 -0
- package/dist/layout/Flow.svelte +46 -0
- package/dist/layout/Flow.svelte.d.ts +16 -0
- package/dist/layout/Grid.svelte +23 -0
- package/dist/layout/Grid.svelte.d.ts +26 -0
- package/dist/layout/HStack.svelte +12 -0
- package/dist/layout/HStack.svelte.d.ts +34 -0
- package/dist/layout/Hero.svelte +76 -0
- package/dist/layout/Hero.svelte.d.ts +36 -0
- package/dist/layout/Navbar.svelte +2 -2
- package/dist/layout/Sidebar.svelte +1 -1
- package/dist/layout/Spacer.svelte +12 -0
- package/dist/layout/Spacer.svelte.d.ts +6 -0
- package/dist/layout/VStack.svelte +12 -0
- package/dist/layout/VStack.svelte.d.ts +29 -0
- package/dist/layout/index.d.ts +9 -0
- package/dist/layout/index.js +9 -0
- package/dist/layout/space.d.ts +44 -0
- package/dist/layout/space.js +76 -0
- package/dist/search/types.d.ts +3 -0
- package/dist/seo/og-image.d.ts +4 -3
- package/dist/seo/og-image.js +4 -3
- package/dist/tips/tip-stack.d.ts +1 -0
- package/dist/tips/tip-store.svelte.d.ts +2 -1
- package/dist/ui/Accordion.svelte +75 -0
- package/dist/ui/Accordion.svelte.d.ts +50 -0
- package/dist/ui/AccordionItem.svelte +73 -0
- package/dist/ui/AccordionItem.svelte.d.ts +18 -0
- package/dist/ui/Button.svelte +3 -2
- package/dist/ui/ButtonGroup.svelte +24 -0
- package/dist/ui/ButtonGroup.svelte.d.ts +17 -0
- package/dist/ui/ContextMenu.svelte +75 -0
- package/dist/ui/ContextMenu.svelte.d.ts +25 -0
- package/dist/ui/Disclosure.svelte +7 -0
- package/dist/ui/Disclosure.svelte.d.ts +2 -2
- package/dist/ui/Divider.svelte +47 -0
- package/dist/ui/Divider.svelte.d.ts +28 -0
- package/dist/ui/DropdownMenu.svelte +44 -0
- package/dist/ui/DropdownMenu.svelte.d.ts +30 -0
- package/dist/ui/Menu.svelte +17 -47
- package/dist/ui/Menu.svelte.d.ts +3 -24
- package/dist/ui/MenuCheckboxItem.svelte +33 -0
- package/dist/ui/MenuCheckboxItem.svelte.d.ts +20 -0
- package/dist/ui/MenuItem.svelte +29 -31
- package/dist/ui/MenuItem.svelte.d.ts +2 -2
- package/dist/ui/MenuRadioGroup.svelte +25 -0
- package/dist/ui/MenuRadioGroup.svelte.d.ts +20 -0
- package/dist/ui/MenuRadioItem.svelte +20 -0
- package/dist/ui/MenuRadioItem.svelte.d.ts +15 -0
- package/dist/ui/MenuSeparator.svelte +12 -11
- package/dist/ui/MenuSub.svelte +24 -0
- package/dist/ui/MenuSub.svelte.d.ts +15 -0
- package/dist/ui/Spinner.svelte +41 -0
- package/dist/ui/Spinner.svelte.d.ts +35 -0
- package/dist/ui/Stack.svelte +36 -0
- package/dist/ui/Stack.svelte.d.ts +48 -0
- package/dist/ui/ToggleButton.svelte +58 -0
- package/dist/ui/ToggleButton.svelte.d.ts +45 -0
- package/dist/ui/ToggleGroup.svelte +142 -0
- package/dist/ui/ToggleGroup.svelte.d.ts +86 -0
- package/dist/ui/Toolbar.svelte +40 -0
- package/dist/ui/Toolbar.svelte.d.ts +20 -0
- package/dist/ui/ToolbarButton.svelte +29 -0
- package/dist/ui/ToolbarButton.svelte.d.ts +21 -0
- package/dist/ui/ToolbarLink.svelte +21 -0
- package/dist/ui/ToolbarLink.svelte.d.ts +12 -0
- package/dist/ui/ToolbarSeparator.svelte +22 -0
- package/dist/ui/ToolbarSeparator.svelte.d.ts +12 -0
- package/dist/ui/ToolbarToggleGroup.svelte +66 -0
- package/dist/ui/ToolbarToggleGroup.svelte.d.ts +52 -0
- package/dist/ui/accordion-context.d.ts +26 -0
- package/dist/ui/accordion-context.js +23 -0
- package/dist/ui/context-menu.d.ts +13 -0
- package/dist/ui/context-menu.js +13 -0
- package/dist/ui/index.d.ts +19 -0
- package/dist/ui/index.js +18 -0
- package/dist/ui/menu-context.d.ts +13 -15
- package/dist/ui/menu-context.js +14 -18
- package/dist/ui/menu-parts/CheckboxItemPart.svelte +26 -0
- package/dist/ui/menu-parts/CheckboxItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/ItemPart.svelte +29 -0
- package/dist/ui/menu-parts/ItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/RadioGroupPart.svelte +24 -0
- package/dist/ui/menu-parts/RadioGroupPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/RadioItemPart.svelte +22 -0
- package/dist/ui/menu-parts/RadioItemPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/SeparatorPart.svelte +16 -0
- package/dist/ui/menu-parts/SeparatorPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/SubPart.svelte +28 -0
- package/dist/ui/menu-parts/SubPart.svelte.d.ts +5 -0
- package/dist/ui/menu-parts/menu-parts.d.ts +104 -0
- package/dist/ui/menu-parts/menu-parts.js +31 -0
- package/dist/ui/menu-parts/parts.d.ts +12 -0
- package/dist/ui/menu-parts/parts.js +27 -0
- package/dist/ui/toggle-classes.d.ts +39 -0
- package/dist/ui/toggle-classes.js +36 -0
- package/dist/ui/tones.d.ts +35 -0
- package/dist/ui/tones.js +90 -0
- package/package.json +34 -18
|
@@ -13,12 +13,29 @@ A pan-and-zoom SVG surface over a `VectorDocument`, with each element drawn by a
|
|
|
13
13
|
## ARIA contract
|
|
14
14
|
|
|
15
15
|
The `<svg>` is `role="application"` named by `label` (default "Vector editing
|
|
16
|
-
canvas"). `application` is the honest role for a surface
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
16
|
+
canvas"). `application` is the honest role for a surface that interprets its
|
|
17
|
+
own input — it tells a screen reader to pass keys through rather than to read
|
|
18
|
+
the SVG as a picture — and it is a promise that the surface HANDLES those
|
|
19
|
+
keys, which § Keys keeps.
|
|
20
|
+
|
|
21
|
+
## Keys
|
|
22
|
+
|
|
23
|
+
When `interactive`, the `<svg>` is one Tab stop, and every keydown and keyup
|
|
24
|
+
on it goes to `onkey` FIRST. What a key means to the elements is the
|
|
25
|
+
application's, for the same reason a pointer gesture is. Only a key the
|
|
26
|
+
application left alone (did not `preventDefault`), and not a Ctrl, Alt or
|
|
27
|
+
Meta chord, falls through to the two bindings this component owns, because
|
|
28
|
+
it owns the viewport:
|
|
29
|
+
|
|
30
|
+
| Key | Does |
|
|
31
|
+
| ----------------------- | -------------------------------------------- |
|
|
32
|
+
| Arrow keys (`pan` tool) | pan by 40 screen pixels; Shift for 160 |
|
|
33
|
+
| `+` / `=`, `-` | zoom in / out about the centre of the view |
|
|
34
|
+
|
|
35
|
+
The application says which of its elements is focused through
|
|
36
|
+
`activedescendant` (an element id inside the surface), so DOM focus stays on
|
|
37
|
+
the `<svg>` and the arrow keys never scroll the page out from under the
|
|
38
|
+
reader.
|
|
22
39
|
|
|
23
40
|
## Two decisions worth stating
|
|
24
41
|
|
|
@@ -38,7 +55,7 @@ A pan-and-zoom SVG surface over a `VectorDocument`, with each element drawn by a
|
|
|
38
55
|
pointer geometry.
|
|
39
56
|
-->
|
|
40
57
|
<script lang="ts" generics="T extends CanvasElement">import { panBy, screenToCanvas, snapToGrid, sortByZIndex, zoomAbout } from "./utils.js";
|
|
41
|
-
let { doc, selected = new Set(), tool = "select", width = 800, height = 600, element, interactive = true, label = "Vector editing canvas", onviewportchange, oninteract, class: className, ...rest } = $props();
|
|
58
|
+
let { doc, selected = new Set(), tool = "select", width = 800, height = 600, element, interactive = true, label = "Vector editing canvas", activedescendant = "", describedby = "", overlay, onkey, onfocuschange, onviewportchange, oninteract, class: className, ...rest } = $props();
|
|
42
59
|
// Scoped to this instance: two canvases on one page would otherwise share a
|
|
43
60
|
// `<pattern id>`, and the second would paint the first's grid.
|
|
44
61
|
const uid = $props.id();
|
|
@@ -168,6 +185,57 @@ const wheel = (event) => {
|
|
|
168
185
|
};
|
|
169
186
|
onviewportchange?.(zoomAbout(doc.viewport, pointer, event.deltaY > 0 ? .9 : 1.1));
|
|
170
187
|
};
|
|
188
|
+
/** Screen pixels one arrow press pans by with the `pan` tool; Shift multiplies it. */
|
|
189
|
+
const PAN_STEP = 40;
|
|
190
|
+
const COARSE_PAN = 4;
|
|
191
|
+
/** Which way the view moves for each arrow: right reveals more of the right. */
|
|
192
|
+
const PAN_DIRECTIONS = new Map([
|
|
193
|
+
["ArrowLeft", {
|
|
194
|
+
x: 1,
|
|
195
|
+
y: 0
|
|
196
|
+
}],
|
|
197
|
+
["ArrowRight", {
|
|
198
|
+
x: -1,
|
|
199
|
+
y: 0
|
|
200
|
+
}],
|
|
201
|
+
["ArrowUp", {
|
|
202
|
+
x: 0,
|
|
203
|
+
y: 1
|
|
204
|
+
}],
|
|
205
|
+
["ArrowDown", {
|
|
206
|
+
x: 0,
|
|
207
|
+
y: -1
|
|
208
|
+
}]
|
|
209
|
+
]);
|
|
210
|
+
/** The zoom factor per key; `=` is `+` without the Shift. */
|
|
211
|
+
const ZOOM_KEYS = new Map([
|
|
212
|
+
["+", 1.1],
|
|
213
|
+
["=", 1.1],
|
|
214
|
+
["-", .9]
|
|
215
|
+
]);
|
|
216
|
+
/** The view's own keys, for whatever the application did not claim. */
|
|
217
|
+
const viewKey = (event) => {
|
|
218
|
+
const factor = ZOOM_KEYS.get(event.key);
|
|
219
|
+
if (factor !== undefined) {
|
|
220
|
+
onviewportchange?.(zoomAbout(doc.viewport, {
|
|
221
|
+
x: width / 2,
|
|
222
|
+
y: height / 2
|
|
223
|
+
}, factor));
|
|
224
|
+
return true;
|
|
225
|
+
}
|
|
226
|
+
const direction = PAN_DIRECTIONS.get(event.key);
|
|
227
|
+
if (tool !== "pan" || direction === undefined) return false;
|
|
228
|
+
const step = PAN_STEP * (event.shiftKey ? COARSE_PAN : 1);
|
|
229
|
+
onviewportchange?.(panBy(doc.viewport, direction.x * step, direction.y * step));
|
|
230
|
+
return true;
|
|
231
|
+
};
|
|
232
|
+
const key = (event) => {
|
|
233
|
+
if (!interactive) return;
|
|
234
|
+
onkey?.(event);
|
|
235
|
+
if (event.type !== "keydown" || event.defaultPrevented) return;
|
|
236
|
+
if (event.ctrlKey || event.metaKey || event.altKey) return;
|
|
237
|
+
if (viewKey(event)) event.preventDefault();
|
|
238
|
+
};
|
|
171
239
|
</script>
|
|
172
240
|
|
|
173
241
|
<div
|
|
@@ -176,6 +244,10 @@ const wheel = (event) => {
|
|
|
176
244
|
style:height="{height}px"
|
|
177
245
|
style:touch-action="none"
|
|
178
246
|
>
|
|
247
|
+
<!-- Svelte's a11y table files `application` under the non-interactive roles;
|
|
248
|
+
ARIA defines it as the role that takes focus and handles its own keys,
|
|
249
|
+
which is exactly what the tabindex and the key handlers are for. -->
|
|
250
|
+
<!-- svelte-ignore a11y_no_noninteractive_tabindex, a11y_no_noninteractive_element_interactions -->
|
|
179
251
|
<svg
|
|
180
252
|
{...rest}
|
|
181
253
|
bind:this={surface}
|
|
@@ -183,7 +255,14 @@ const wheel = (event) => {
|
|
|
183
255
|
{height}
|
|
184
256
|
role="application"
|
|
185
257
|
aria-label={label}
|
|
186
|
-
|
|
258
|
+
aria-activedescendant={activedescendant === '' ? undefined : activedescendant}
|
|
259
|
+
aria-describedby={describedby === '' ? undefined : describedby}
|
|
260
|
+
tabindex={interactive ? 0 : undefined}
|
|
261
|
+
class="focus-visible:outline-primary cursor-crosshair focus:outline-none focus-visible:outline-2 focus-visible:-outline-offset-2"
|
|
262
|
+
onkeydown={key}
|
|
263
|
+
onkeyup={key}
|
|
264
|
+
onfocus={() => onfocuschange?.(true)}
|
|
265
|
+
onblur={() => onfocuschange?.(false)}
|
|
187
266
|
onpointerdown={down}
|
|
188
267
|
onpointermove={move}
|
|
189
268
|
onpointerup={up}
|
|
@@ -234,6 +313,8 @@ const wheel = (event) => {
|
|
|
234
313
|
{/if}
|
|
235
314
|
</g>
|
|
236
315
|
{/each}
|
|
316
|
+
|
|
317
|
+
{@render overlay?.()}
|
|
237
318
|
</g>
|
|
238
319
|
</svg>
|
|
239
320
|
</div>
|
|
@@ -2,7 +2,7 @@ import type { Snippet } from 'svelte';
|
|
|
2
2
|
import type { SVGAttributes } from 'svelte/elements';
|
|
3
3
|
import type { CanvasElement, Point, VectorDocument, Viewport } from './types.ts';
|
|
4
4
|
declare function $$render<T extends CanvasElement>(): {
|
|
5
|
-
props: Omit<SVGAttributes<SVGSVGElement>, "class" | "height" | "width"> & {
|
|
5
|
+
props: Omit<SVGAttributes<SVGSVGElement>, "class" | "onfocus" | "onblur" | "onkeydown" | "onkeyup" | "height" | "width"> & {
|
|
6
6
|
/** The document to draw: its elements, viewport and grid. */
|
|
7
7
|
doc: VectorDocument<T>;
|
|
8
8
|
/**
|
|
@@ -37,6 +37,24 @@ declare function $$render<T extends CanvasElement>(): {
|
|
|
37
37
|
* @defaultValue `'Vector editing canvas'`
|
|
38
38
|
*/
|
|
39
39
|
label?: string | undefined;
|
|
40
|
+
/**
|
|
41
|
+
* The id of the element that has keyboard focus inside the surface, for
|
|
42
|
+
* `aria-activedescendant`; `''` for none.
|
|
43
|
+
* @defaultValue `''`
|
|
44
|
+
*/
|
|
45
|
+
activedescendant?: string | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* The id of an element describing the surface's keys, for
|
|
48
|
+
* `aria-describedby`; `''` for none.
|
|
49
|
+
* @defaultValue `''`
|
|
50
|
+
*/
|
|
51
|
+
describedby?: string | undefined;
|
|
52
|
+
/** Drawn above every element, in canvas coordinates: a cursor, a guide. */
|
|
53
|
+
overlay?: Snippet<[]> | undefined;
|
|
54
|
+
/** Every keydown and keyup on the surface, before its own keys; `preventDefault` claims the key. */
|
|
55
|
+
onkey?: ((event: KeyboardEvent) => void) | undefined;
|
|
56
|
+
/** Whether the surface has keyboard focus, each time that changes. */
|
|
57
|
+
onfocuschange?: ((focused: boolean) => void) | undefined;
|
|
40
58
|
/**
|
|
41
59
|
* The viewport after a pan or a zoom.
|
|
42
60
|
*
|
package/dist/canvas/types.d.ts
CHANGED
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
*
|
|
11
11
|
* @module @thomasfosterau/components/canvas/types
|
|
12
12
|
*/
|
|
13
|
-
/** Stable identity for
|
|
13
|
+
/** Stable identity for a canvas element. */
|
|
14
14
|
export type ElementId = string;
|
|
15
15
|
/** A point in canvas coordinates — the document's own space, not the screen's. */
|
|
16
16
|
export interface Point {
|
package/dist/charts/types.d.ts
CHANGED
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
* the index it was asked to format.
|
|
19
19
|
*/
|
|
20
20
|
export const formatListParts = (items, options = {}) => {
|
|
21
|
-
|
|
21
|
+
// A mutable copy: TS6's `Intl.ListFormat` (svelte-check) takes no readonly array.
|
|
22
|
+
const { locales } = options;
|
|
23
|
+
const format = new Intl.ListFormat(typeof locales === 'object' ? [...locales] : locales, {
|
|
22
24
|
style: options.style ?? 'long',
|
|
23
25
|
type: options.type ?? 'conjunction',
|
|
24
26
|
});
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
One message of a `MessageThread`: author, time, avatar, the body and a status line, as a daisyUI `chat` bubble.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
ChatBubble — an `<li>` holding an `<article>` named by its header, so a
|
|
6
|
+
reader moves message to message and hears "Ada Lovelace, 3 minutes ago"
|
|
7
|
+
before the body. The time is a real `<time datetime>` (`DateTime`, or
|
|
8
|
+
`RelativeTime` with the absolute instant in `title`). The avatar is
|
|
9
|
+
decorative (`aria-hidden`): the author's name is already text.
|
|
10
|
+
|
|
11
|
+
`side` is visual only: messages from the viewer sit at the end, and the
|
|
12
|
+
author string ("You") is what says whose they are, never the position or
|
|
13
|
+
the colour. The `<article>` is the daisyUI `chat` grid itself, so its
|
|
14
|
+
image / header / bubble / footer are its direct children, as
|
|
15
|
+
`chat.css` requires.
|
|
16
|
+
-->
|
|
17
|
+
<script lang="ts">import DateTime from "../formatting/DateTime.svelte";
|
|
18
|
+
import RelativeTime from "../formatting/RelativeTime.svelte";
|
|
19
|
+
import { chatBubbleTone } from "../ui/tones.js";
|
|
20
|
+
let { author, sentAt, side = "start", tone, relative = false, locales, avatar, footer, children, class: className, ...rest } = $props();
|
|
21
|
+
const uid = $props.id();
|
|
22
|
+
const headerId = `${uid}-header`;
|
|
23
|
+
const sideClass = {
|
|
24
|
+
start: "chat-start",
|
|
25
|
+
end: "chat-end"
|
|
26
|
+
};
|
|
27
|
+
</script>
|
|
28
|
+
|
|
29
|
+
<li>
|
|
30
|
+
<article {...rest} aria-labelledby={headerId} class={['chat', sideClass[side], className]}>
|
|
31
|
+
{#if avatar}
|
|
32
|
+
<div class="chat-image avatar" aria-hidden="true">{@render avatar()}</div>
|
|
33
|
+
{/if}
|
|
34
|
+
<div class="chat-header" id={headerId}>
|
|
35
|
+
{author}{#if sentAt !== undefined}<span class="sr-only">,</span>
|
|
36
|
+
{#if relative}
|
|
37
|
+
<RelativeTime value={sentAt} {locales} class="text-xs opacity-60" />
|
|
38
|
+
{:else}
|
|
39
|
+
<DateTime value={sentAt} {locales} dateStyle="medium" timeStyle="short" class="text-xs opacity-60" />
|
|
40
|
+
{/if}
|
|
41
|
+
{/if}
|
|
42
|
+
</div>
|
|
43
|
+
<div class={['chat-bubble', tone !== undefined && chatBubbleTone[tone]]}>{@render children()}</div>
|
|
44
|
+
{#if footer}
|
|
45
|
+
<div class="chat-footer opacity-60">{@render footer()}</div>
|
|
46
|
+
{/if}
|
|
47
|
+
</article>
|
|
48
|
+
</li>
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
import { type Tone } from '../ui/tones.ts';
|
|
4
|
+
interface Props extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
|
|
5
|
+
/** Display name of the author; part of the message's accessible name. */
|
|
6
|
+
author: string;
|
|
7
|
+
/** When it was sent: a `Date`, epoch milliseconds or an ISO string. */
|
|
8
|
+
sentAt?: Date | number | string | undefined;
|
|
9
|
+
/**
|
|
10
|
+
* `'end'` for the viewer's own messages.
|
|
11
|
+
* @defaultValue `'start'`
|
|
12
|
+
*/
|
|
13
|
+
side?: 'start' | 'end' | undefined;
|
|
14
|
+
/** Bubble colour. Omitted, daisyUI's neutral bubble. */
|
|
15
|
+
tone?: Tone | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Show `sentAt` relative ("3 minutes ago") rather than absolute.
|
|
18
|
+
* @defaultValue `false`
|
|
19
|
+
*/
|
|
20
|
+
relative?: boolean | undefined;
|
|
21
|
+
/** Locale(s) for the time; falls back to the components context. */
|
|
22
|
+
locales?: string | readonly string[] | undefined;
|
|
23
|
+
/** The avatar (an `Avatar` or an image); decorative here. */
|
|
24
|
+
avatar?: Snippet<[]> | undefined;
|
|
25
|
+
/** Status line under the bubble ("Delivered", "Edited"). */
|
|
26
|
+
footer?: Snippet<[]> | undefined;
|
|
27
|
+
/** The message body. */
|
|
28
|
+
children: Snippet<[]>;
|
|
29
|
+
}
|
|
30
|
+
/** One message of a `MessageThread`: author, time, avatar, the body and a status line, as a daisyUI `chat` bubble. */
|
|
31
|
+
declare const ChatBubble: import("svelte").Component<Props, {}, "">;
|
|
32
|
+
type ChatBubble = ReturnType<typeof ChatBubble>;
|
|
33
|
+
export default ChatBubble;
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
<!-- @component
|
|
2
|
-
Label/value pairs as a `grid`, a bordered `card`, `divided` rows or `
|
|
2
|
+
Label/value pairs as a `grid`, a bordered `card`, `divided` rows, `inline` pairs, or `bare` pairs in a layout the caller supplies.
|
|
3
3
|
-->
|
|
4
4
|
<!--
|
|
5
5
|
DescriptionList — label / value pairs, in the four shapes a detail page
|
|
6
6
|
wants them: a two-column `grid`, a bordered `card` with the labels in a
|
|
7
|
-
fixed gutter, `divided` rows, or `inline` pairs running across a line
|
|
7
|
+
fixed gutter, `divided` rows, or `inline` pairs running across a line —
|
|
8
|
+
or `bare`, which adds no layout of its own: the `<dl>` takes only the
|
|
9
|
+
caller's `class` (say `grid grid-cols-[auto_1fr] gap-x-4`) and every
|
|
10
|
+
row's `<dt>`/`<dd>` is a direct child of it, so a consumer-owned grid can
|
|
11
|
+
mix `DescriptionRow`s with its own `<dt>`/`<dd>` pairs and keep its columns.
|
|
8
12
|
|
|
9
13
|
One component rather than the two the apps had. They had split it by how the
|
|
10
14
|
VALUE arrives — one took rows as strings, the other took them as markup —
|
|
@@ -30,7 +34,9 @@ const listClass = {
|
|
|
30
34
|
grid: "grid grid-cols-1 gap-3 sm:grid-cols-2",
|
|
31
35
|
card: "card card-border card-body bg-base-100 grid grid-cols-1 gap-x-6 gap-y-3 sm:grid-cols-[12rem_1fr]",
|
|
32
36
|
divided: "divide-base-300 divide-y",
|
|
33
|
-
inline: "flex flex-wrap gap-x-6 gap-y-2"
|
|
37
|
+
inline: "flex flex-wrap gap-x-6 gap-y-2",
|
|
38
|
+
// The caller's `class` is the whole layout.
|
|
39
|
+
bare: ""
|
|
34
40
|
};
|
|
35
41
|
// A getter, not a snapshot: the rows re-read it, so a list whose `variant`
|
|
36
42
|
// changes re-styles the rows it already mounted.
|
|
@@ -20,7 +20,7 @@ interface Props extends HTMLAttributes<HTMLElement> {
|
|
|
20
20
|
/** The rows — `DescriptionRow`s, or any other `<dt>`/`<dd>` pairs. */
|
|
21
21
|
children: Snippet<[]>;
|
|
22
22
|
}
|
|
23
|
-
/** Label/value pairs as a `grid`, a bordered `card`, `divided` rows or `
|
|
23
|
+
/** Label/value pairs as a `grid`, a bordered `card`, `divided` rows, `inline` pairs, or `bare` pairs in a layout the caller supplies. */
|
|
24
24
|
declare const DescriptionList: import("svelte").Component<Props, {}, "">;
|
|
25
25
|
type DescriptionList = ReturnType<typeof DescriptionList>;
|
|
26
26
|
export default DescriptionList;
|
|
@@ -12,10 +12,11 @@ One label and its value inside a `DescriptionList`.
|
|
|
12
12
|
Both settings come from the enclosing list by default and can be overridden
|
|
13
13
|
per row.
|
|
14
14
|
|
|
15
|
-
The `card`
|
|
16
|
-
directly in the list's two-column grid
|
|
17
|
-
|
|
18
|
-
|
|
15
|
+
The `card` and `bare` variants' `<dt>` and `<dd>` are siblings of every
|
|
16
|
+
other row's, directly in the `<dl>` (the list's own two-column grid for
|
|
17
|
+
`card`, whatever layout the caller gave it for `bare`): a wrapper would
|
|
18
|
+
break the alignment the grid exists for. Every other variant wraps the
|
|
19
|
+
pair, so the two stay together when the rows wrap.
|
|
19
20
|
|
|
20
21
|
ARIA contract: the `<dt>`/`<dd>` pairing is the whole contract — nothing is
|
|
21
22
|
added to it, and nothing needs to be.
|
|
@@ -43,7 +44,7 @@ const ddClass = $derived([
|
|
|
43
44
|
{/snippet}
|
|
44
45
|
|
|
45
46
|
{#if visible}
|
|
46
|
-
{#if style().variant === 'card'}
|
|
47
|
+
{#if style().variant === 'card' || style().variant === 'bare'}
|
|
47
48
|
{@render pair()}
|
|
48
49
|
{:else if style().variant === 'inline'}
|
|
49
50
|
<div class="flex items-baseline gap-2">{@render pair()}</div>
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
<!-- @component
|
|
2
|
+
A conversation: a named region holding an ordered list of `ChatBubble`s.
|
|
3
|
+
-->
|
|
4
|
+
<!--
|
|
5
|
+
MessageThread — comments on a planting, a support thread, a note from the
|
|
6
|
+
garden coordinator. A `<section aria-label>` (a `region` a reader can jump
|
|
7
|
+
to) around an `<ol>`, because order is the content. Its children are
|
|
8
|
+
`ChatBubble`s, each an `<li>`.
|
|
9
|
+
|
|
10
|
+
`live` is for a thread that grows while it is read (live chat): the
|
|
11
|
+
section becomes `role="log"`, which announces appended messages politely.
|
|
12
|
+
Off by default, because a static comment history must not read itself
|
|
13
|
+
out as it renders.
|
|
14
|
+
-->
|
|
15
|
+
<script lang="ts">let { label, live = false, children, class: className, ...rest } = $props();
|
|
16
|
+
export {};
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<section
|
|
20
|
+
{...rest}
|
|
21
|
+
aria-label={label}
|
|
22
|
+
role={live ? 'log' : undefined}
|
|
23
|
+
aria-live={live ? 'polite' : undefined}
|
|
24
|
+
class={className}
|
|
25
|
+
>
|
|
26
|
+
<ol class="flex list-none flex-col gap-1 p-0">
|
|
27
|
+
{@render children()}
|
|
28
|
+
</ol>
|
|
29
|
+
</section>
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
|
+
interface Props extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
|
|
4
|
+
/** Accessible name, e.g. `'Comments on Bed 4'`. */
|
|
5
|
+
label: string;
|
|
6
|
+
/**
|
|
7
|
+
* Announce new messages as they arrive (`role="log"`).
|
|
8
|
+
* @defaultValue `false`
|
|
9
|
+
*/
|
|
10
|
+
live?: boolean | undefined;
|
|
11
|
+
/** The `ChatBubble`s, oldest first. */
|
|
12
|
+
children: Snippet<[]>;
|
|
13
|
+
}
|
|
14
|
+
/** A conversation: a named region holding an ordered list of `ChatBubble`s. */
|
|
15
|
+
declare const MessageThread: import("svelte").Component<Props, {}, "">;
|
|
16
|
+
type MessageThread = ReturnType<typeof MessageThread>;
|
|
17
|
+
export default MessageThread;
|
|
@@ -33,7 +33,7 @@ Offset-based page navigation: numbered links with gaps or a bare Previous/Next p
|
|
|
33
33
|
import { getComponentsContext } from "../context.svelte.js";
|
|
34
34
|
import { buttonSize } from "../ui/tones.js";
|
|
35
35
|
import { pageWindow } from "./pagination.js";
|
|
36
|
-
let { offset, limit, total, variant = "window", href, onPage, siblings = 1, label = "Pagination", previousLabel = "Previous", nextLabel = "Next", pageLabel = (page) => `Page ${page}`, size = "sm", showRange = false, rangeLabel, statusLabel, locales = getComponentsContext().locale(), class: className, ...rest } = $props();
|
|
36
|
+
let { offset, limit, total, variant = "window", href, onPage, siblings = 1, label = "Pagination", previousLabel = "Previous", nextLabel = "Next", pageLabel = (page) => `Page ${page}`, formatPage = (page) => String(page), size = "sm", showRange = false, rangeLabel, statusLabel, locales = getComponentsContext().locale(), class: className, ...rest } = $props();
|
|
37
37
|
const context = getComponentsContext();
|
|
38
38
|
const view = $derived(pageWindow({
|
|
39
39
|
offset,
|
|
@@ -42,7 +42,7 @@ const view = $derived(pageWindow({
|
|
|
42
42
|
// The formatter and the formatted string are separate `$derived`s so the
|
|
43
43
|
// (relatively expensive) `Intl.NumberFormat` is not rebuilt when only the
|
|
44
44
|
// offset moves. Counts are quantities and get grouped; the page NUMBERS
|
|
45
|
-
// below are identifiers and stay bare.
|
|
45
|
+
// below are identifiers and stay bare unless `formatPage` says otherwise.
|
|
46
46
|
const counts = $derived(new Intl.NumberFormat(locales));
|
|
47
47
|
const rangeText = $derived(rangeLabel === undefined ? `Showing ${counts.format(view.from)}–${counts.format(view.to)} of ${counts.format(total)}` : rangeLabel(view.from, view.to, total));
|
|
48
48
|
/** A target offset's href, resolved through the context. */
|
|
@@ -104,11 +104,11 @@ const inertClass = $derived(["btn btn-disabled join-item", buttonSize[size]]);
|
|
|
104
104
|
{:else if item.current}
|
|
105
105
|
<span class={['btn btn-active join-item', buttonSize[size]]} aria-current="page">
|
|
106
106
|
<span class="sr-only">{pageLabel(item.page)}</span>
|
|
107
|
-
<span aria-hidden="true">{item.page}</span>
|
|
107
|
+
<span aria-hidden="true">{formatPage(item.page)}</span>
|
|
108
108
|
</span>
|
|
109
109
|
{:else if href !== undefined}
|
|
110
110
|
<a href={linkTo(item.offset)} class={itemClass} aria-label={pageLabel(item.page)}>
|
|
111
|
-
<span aria-hidden="true">{item.page}</span>
|
|
111
|
+
<span aria-hidden="true">{formatPage(item.page)}</span>
|
|
112
112
|
</a>
|
|
113
113
|
{:else}
|
|
114
114
|
<button
|
|
@@ -119,7 +119,7 @@ const inertClass = $derived(["btn btn-disabled join-item", buttonSize[size]]);
|
|
|
119
119
|
onPage?.(item.offset);
|
|
120
120
|
}}
|
|
121
121
|
>
|
|
122
|
-
<span aria-hidden="true">{item.page}</span>
|
|
122
|
+
<span aria-hidden="true">{formatPage(item.page)}</span>
|
|
123
123
|
</button>
|
|
124
124
|
{/if}
|
|
125
125
|
</li>
|
|
@@ -45,6 +45,14 @@ interface Props extends Omit<HTMLAttributes<HTMLElement>, 'children'> {
|
|
|
45
45
|
* @defaultValue `"Page <page>"`
|
|
46
46
|
*/
|
|
47
47
|
pageLabel?: ((page: number) => string) | undefined;
|
|
48
|
+
/**
|
|
49
|
+
* How a page number is written on its control — the visible digits only;
|
|
50
|
+
* `pageLabel` is the accessible name. Page numbers are identifiers, so they
|
|
51
|
+
* are bare by default; pass e.g. `(page) => new Intl.NumberFormat('en-AU').format(page)`
|
|
52
|
+
* to group them ("1,000").
|
|
53
|
+
* @defaultValue `String(page)`
|
|
54
|
+
*/
|
|
55
|
+
formatPage?: ((page: number) => string) | undefined;
|
|
48
56
|
/**
|
|
49
57
|
* daisyUI size step.
|
|
50
58
|
* @defaultValue `'sm'`
|
|
@@ -18,7 +18,7 @@ The count line and the pager that sit under a paginated index page.
|
|
|
18
18
|
-->
|
|
19
19
|
<script lang="ts">import Pagination from "./Pagination.svelte";
|
|
20
20
|
import ResultCount from "./ResultCount.svelte";
|
|
21
|
-
let { shown, offset, limit, total, href, onPage, variant = "window", siblings = 1, size = "sm", label = "Pagination", previousLabel = "Previous", nextLabel = "Next", pageLabel, countLabel, locales, class: className, ...rest } = $props();
|
|
21
|
+
let { shown, offset, limit, total, href, onPage, variant = "window", siblings = 1, size = "sm", label = "Pagination", previousLabel = "Previous", nextLabel = "Next", pageLabel, formatPage, countLabel, locales, class: className, ...rest } = $props();
|
|
22
22
|
</script>
|
|
23
23
|
|
|
24
24
|
<div {...rest} class={['space-y-4', className]}>
|
|
@@ -36,6 +36,7 @@ let { shown, offset, limit, total, href, onPage, variant = "window", siblings =
|
|
|
36
36
|
{previousLabel}
|
|
37
37
|
{nextLabel}
|
|
38
38
|
{pageLabel}
|
|
39
|
+
{formatPage}
|
|
39
40
|
{locales}
|
|
40
41
|
/>
|
|
41
42
|
</div>
|
|
@@ -45,6 +45,8 @@ interface Props extends Omit<HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
|
45
45
|
nextLabel?: string | undefined;
|
|
46
46
|
/** How a numbered control is named; see `Pagination`. */
|
|
47
47
|
pageLabel?: ((page: number) => string) | undefined;
|
|
48
|
+
/** Passed to `Pagination`: how a page number's visible digits are written. */
|
|
49
|
+
formatPage?: ((page: number) => string) | undefined;
|
|
48
50
|
/** The count line, when "Showing x of y" is not the sentence wanted. */
|
|
49
51
|
countLabel?: ((shown: number, total: number) => string) | undefined;
|
|
50
52
|
/**
|
package/dist/data/Table.svelte
CHANGED
|
@@ -76,6 +76,10 @@ const rowAttributes = (row) => onSelect === undefined ? {} : {
|
|
|
76
76
|
};
|
|
77
77
|
</script>
|
|
78
78
|
|
|
79
|
+
{#snippet cellBody(column: TableColumn<T>, row: T)}
|
|
80
|
+
{#if column.cell}{@render column.cell(row)}{:else}{column.value(row)}{/if}
|
|
81
|
+
{/snippet}
|
|
82
|
+
|
|
79
83
|
<div class={['overflow-x-auto', containerClass]}>
|
|
80
84
|
<table
|
|
81
85
|
{...rest}
|
|
@@ -128,9 +132,11 @@ const rowAttributes = (row) => onSelect === undefined ? {} : {
|
|
|
128
132
|
{#each rows as row (rowKey(row))}
|
|
129
133
|
<tr class="hover:bg-base-200" {...rowAttributes(row)}>
|
|
130
134
|
{#each columns as column (column.key)}
|
|
131
|
-
|
|
132
|
-
{
|
|
133
|
-
|
|
135
|
+
{#if column.rowHeader}
|
|
136
|
+
<th scope="row" class={['font-normal', columnClass(column)]}>{@render cellBody(column, row)}</th>
|
|
137
|
+
{:else}
|
|
138
|
+
<td class={columnClass(column)}>{@render cellBody(column, row)}</td>
|
|
139
|
+
{/if}
|
|
134
140
|
{/each}
|
|
135
141
|
</tr>
|
|
136
142
|
{/each}
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* How a {@link DescriptionRow} learns which {@link DescriptionList} it is
|
|
3
3
|
* inside.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
* wrapper holding a stacked `<dt>`/`<dd>` pair, while a `card`
|
|
7
|
-
* and `<dd>` are
|
|
8
|
-
* wrapper would break the alignment
|
|
9
|
-
* the
|
|
5
|
+
* The list variants render their rows differently — a `grid` row is a
|
|
6
|
+
* wrapper holding a stacked `<dt>`/`<dd>` pair, while a `card` or `bare`
|
|
7
|
+
* row's `<dt>` and `<dd>` are direct children of the `<dl>`, because a
|
|
8
|
+
* wrapper would break the alignment of a two-column grid (the list's own for
|
|
9
|
+
* `card`, the consumer's for `bare`). A call site writes the same
|
|
10
|
+
* `<DescriptionRow>` either way.
|
|
10
11
|
*
|
|
11
12
|
* The variant travels down as context rather than as a prop so a caller
|
|
12
13
|
* cannot get a list and its rows out of step, and so the list stays the
|
|
@@ -17,7 +18,12 @@
|
|
|
17
18
|
*/
|
|
18
19
|
/** The presentation a `DescriptionList` asks its rows for. */
|
|
19
20
|
export interface DescriptionListStyle {
|
|
20
|
-
|
|
21
|
+
/**
|
|
22
|
+
* The layout. `bare` adds no layout classes to the list and renders each
|
|
23
|
+
* row's `<dt>`/`<dd>` as direct children of the `<dl>`, for a consumer that
|
|
24
|
+
* lays the list out itself.
|
|
25
|
+
*/
|
|
26
|
+
readonly variant: 'grid' | 'card' | 'divided' | 'inline' | 'bare';
|
|
21
27
|
/** Render values in a fixed-width face that breaks anywhere. */
|
|
22
28
|
readonly mono: boolean;
|
|
23
29
|
/** Render a row whose value is empty, using `emptyLabel`. */
|
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
* How a {@link DescriptionRow} learns which {@link DescriptionList} it is
|
|
3
3
|
* inside.
|
|
4
4
|
*
|
|
5
|
-
* The
|
|
6
|
-
* wrapper holding a stacked `<dt>`/`<dd>` pair, while a `card`
|
|
7
|
-
* and `<dd>` are
|
|
8
|
-
* wrapper would break the alignment
|
|
9
|
-
* the
|
|
5
|
+
* The list variants render their rows differently — a `grid` row is a
|
|
6
|
+
* wrapper holding a stacked `<dt>`/`<dd>` pair, while a `card` or `bare`
|
|
7
|
+
* row's `<dt>` and `<dd>` are direct children of the `<dl>`, because a
|
|
8
|
+
* wrapper would break the alignment of a two-column grid (the list's own for
|
|
9
|
+
* `card`, the consumer's for `bare`). A call site writes the same
|
|
10
|
+
* `<DescriptionRow>` either way.
|
|
10
11
|
*
|
|
11
12
|
* The variant travels down as context rather than as a prop so a caller
|
|
12
13
|
* cannot get a list and its rows out of step, and so the list stays the
|
package/dist/data/index.d.ts
CHANGED
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @module
|
|
18
18
|
*/
|
|
19
|
+
export { default as ChatBubble } from './ChatBubble.svelte';
|
|
19
20
|
export { default as DataGrid } from './DataGrid.svelte';
|
|
20
21
|
export { default as DescriptionList } from './DescriptionList.svelte';
|
|
21
22
|
export { default as DescriptionRow } from './DescriptionRow.svelte';
|
|
22
23
|
export { default as DiffText } from './DiffText.svelte';
|
|
23
24
|
export { default as ItemList } from './ItemList.svelte';
|
|
24
25
|
export { default as LinkListItem } from './LinkListItem.svelte';
|
|
26
|
+
export { default as MessageThread } from './MessageThread.svelte';
|
|
25
27
|
export { default as Pagination } from './Pagination.svelte';
|
|
26
28
|
export { default as PaginationFooter } from './PaginationFooter.svelte';
|
|
27
29
|
export { default as ResultCount } from './ResultCount.svelte';
|
package/dist/data/index.js
CHANGED
|
@@ -16,12 +16,14 @@
|
|
|
16
16
|
*
|
|
17
17
|
* @module
|
|
18
18
|
*/
|
|
19
|
+
export { default as ChatBubble } from './ChatBubble.svelte';
|
|
19
20
|
export { default as DataGrid } from './DataGrid.svelte';
|
|
20
21
|
export { default as DescriptionList } from './DescriptionList.svelte';
|
|
21
22
|
export { default as DescriptionRow } from './DescriptionRow.svelte';
|
|
22
23
|
export { default as DiffText } from './DiffText.svelte';
|
|
23
24
|
export { default as ItemList } from './ItemList.svelte';
|
|
24
25
|
export { default as LinkListItem } from './LinkListItem.svelte';
|
|
26
|
+
export { default as MessageThread } from './MessageThread.svelte';
|
|
25
27
|
export { default as Pagination } from './Pagination.svelte';
|
|
26
28
|
export { default as PaginationFooter } from './PaginationFooter.svelte';
|
|
27
29
|
export { default as ResultCount } from './ResultCount.svelte';
|
|
@@ -34,6 +34,13 @@ export interface TableColumn<T> {
|
|
|
34
34
|
readonly cell?: Snippet<[T]> | undefined;
|
|
35
35
|
/** Whether the header offers a sort control on this column. */
|
|
36
36
|
readonly sortable?: boolean | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Render this column's body cells as `<th scope="row">` — the row's header,
|
|
39
|
+
* so a screen reader moving down another column announces it with each cell
|
|
40
|
+
* ("Jane Smith, 48,000"). Give it to the column that names the row, usually
|
|
41
|
+
* one per table.
|
|
42
|
+
*/
|
|
43
|
+
readonly rowHeader?: boolean | undefined;
|
|
37
44
|
/** Right-align numeric columns. */
|
|
38
45
|
readonly align?: 'start' | 'end' | undefined;
|
|
39
46
|
/** Extra classes on this column's header and body cells. */
|