@lavalogic/scoria 0.40.4 → 0.40.6
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/dist/Components/Nav/NavServiceMenuList.svelte +20 -1
- package/dist/Components/OptionCards.svelte +107 -0
- package/dist/Components/OptionCards.svelte.d.ts +34 -0
- package/dist/Components/OptionCardsProps.d.ts +19 -0
- package/dist/Components/OptionCardsProps.js +1 -0
- package/dist/Types/Internal/OptionCard.d.ts +17 -0
- package/dist/Types/Internal/OptionCard.js +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/package.json +1 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<svelte:options runes />
|
|
2
2
|
|
|
3
3
|
<script lang="ts">
|
|
4
|
+
import { page } from '$app/state';
|
|
4
5
|
import { Colour } from '../../scss/colours.js';
|
|
5
6
|
import { Size } from '../../Types/Internal/Size.js';
|
|
6
7
|
import Icon from '../Icon.svelte';
|
|
@@ -9,6 +10,21 @@
|
|
|
9
10
|
import ServiceMenuItem from './ServiceMenuItem.svelte';
|
|
10
11
|
|
|
11
12
|
const { title, items, icon }: NavServiceMenuListProps = $props();
|
|
13
|
+
|
|
14
|
+
// Only the single most-specific item is active: the longest item path that
|
|
15
|
+
// the current URL matches. Without this a nested route (e.g.
|
|
16
|
+
// /reports/manage-reports) would also light up its parent item (/reports).
|
|
17
|
+
const activePath = $derived.by(() => {
|
|
18
|
+
const pathname = page.url.pathname;
|
|
19
|
+
let best: string | null = null;
|
|
20
|
+
for (const { item } of items) {
|
|
21
|
+
const path = item.path;
|
|
22
|
+
if (path && pathname.includes(path) && (best === null || path.length > best.length)) {
|
|
23
|
+
best = path;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return best;
|
|
27
|
+
});
|
|
12
28
|
</script>
|
|
13
29
|
|
|
14
30
|
<div
|
|
@@ -35,7 +51,10 @@
|
|
|
35
51
|
role="list"
|
|
36
52
|
>
|
|
37
53
|
{#each items as { item } (item.label)}
|
|
38
|
-
<ServiceMenuItem
|
|
54
|
+
<ServiceMenuItem
|
|
55
|
+
{item}
|
|
56
|
+
selected={item.path != null && item.path === activePath}
|
|
57
|
+
/>
|
|
39
58
|
{/each}
|
|
40
59
|
</div>
|
|
41
60
|
</div>
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<!--
|
|
4
|
+
@component
|
|
5
|
+
A single-select group of large, clickable cards — each an optional leading
|
|
6
|
+
icon, a label, and optional helper text. Use it instead of a `SingleSelect`
|
|
7
|
+
when the choices benefit from a sentence of explanation (e.g. picking a
|
|
8
|
+
report's delivery method or output format).
|
|
9
|
+
|
|
10
|
+
Controlled: pass `selected` and update it in `onchange`. Accessible as a
|
|
11
|
+
native radio group (the radio inputs are visually hidden but focusable).
|
|
12
|
+
-->
|
|
13
|
+
<script
|
|
14
|
+
lang="ts"
|
|
15
|
+
generics="T"
|
|
16
|
+
>
|
|
17
|
+
import { Colour } from '../scss/colours.js';
|
|
18
|
+
import { Size } from '../Types/Internal/Size.js';
|
|
19
|
+
import type { OptionCardsProps } from './OptionCardsProps.js';
|
|
20
|
+
import Icon from './Icon.svelte';
|
|
21
|
+
|
|
22
|
+
let { name, options, selected, onchange }: OptionCardsProps<T> = $props();
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<div
|
|
26
|
+
class="option-cards"
|
|
27
|
+
role="radiogroup"
|
|
28
|
+
>
|
|
29
|
+
{#each options as option (option.value)}
|
|
30
|
+
{@const isSelected = selected === option.value}
|
|
31
|
+
<label
|
|
32
|
+
class="card"
|
|
33
|
+
class:selected={isSelected}
|
|
34
|
+
>
|
|
35
|
+
<input
|
|
36
|
+
class="native"
|
|
37
|
+
type="radio"
|
|
38
|
+
{name}
|
|
39
|
+
checked={isSelected}
|
|
40
|
+
onchange={() => void onchange?.(option.value)}
|
|
41
|
+
/>
|
|
42
|
+
{#if option.icon}
|
|
43
|
+
<Icon
|
|
44
|
+
name={option.icon}
|
|
45
|
+
size={Size.Large}
|
|
46
|
+
colour={isSelected ? Colour['$brand-primary'] : Colour['$ui-blue-14']}
|
|
47
|
+
/>
|
|
48
|
+
{/if}
|
|
49
|
+
<span class="title">{option.label}</span>
|
|
50
|
+
{#if option.info}
|
|
51
|
+
<span class="info">{option.info}</span>
|
|
52
|
+
{/if}
|
|
53
|
+
</label>
|
|
54
|
+
{/each}
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<style>.option-cards {
|
|
58
|
+
display: flex;
|
|
59
|
+
flex-flow: row wrap;
|
|
60
|
+
gap: 0.75rem;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
.card {
|
|
64
|
+
flex: 1 1 0;
|
|
65
|
+
min-width: 9rem;
|
|
66
|
+
display: flex;
|
|
67
|
+
flex-flow: column nowrap;
|
|
68
|
+
gap: 0.25rem;
|
|
69
|
+
padding: 0.85rem 1rem;
|
|
70
|
+
border: solid 1px #cbd4da;
|
|
71
|
+
border-radius: 4px;
|
|
72
|
+
background-color: #ffffff;
|
|
73
|
+
color: #647d8e;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/* Visually hidden but keyboard-focusable (drives :focus-within). */
|
|
78
|
+
.native {
|
|
79
|
+
position: absolute;
|
|
80
|
+
width: 1px;
|
|
81
|
+
height: 1px;
|
|
82
|
+
opacity: 0;
|
|
83
|
+
pointer-events: none;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
.title {
|
|
87
|
+
color: #3a4952;
|
|
88
|
+
font-weight: 600;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
.info {
|
|
92
|
+
font-size: 0.8rem;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
.card.selected {
|
|
96
|
+
border-color: #259fc7;
|
|
97
|
+
background-color: #f4fbfd;
|
|
98
|
+
color: #259fc7;
|
|
99
|
+
}
|
|
100
|
+
.card.selected .title {
|
|
101
|
+
color: #259fc7;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.card:focus-within {
|
|
105
|
+
outline: solid 2px #259fc7;
|
|
106
|
+
outline-offset: 2px;
|
|
107
|
+
}</style>
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { OptionCardsProps } from './OptionCardsProps.js';
|
|
2
|
+
declare function $$render<T>(): {
|
|
3
|
+
props: OptionCardsProps<T>;
|
|
4
|
+
exports: {};
|
|
5
|
+
bindings: "";
|
|
6
|
+
slots: {};
|
|
7
|
+
events: {};
|
|
8
|
+
};
|
|
9
|
+
declare class __sveltets_Render<T> {
|
|
10
|
+
props(): ReturnType<typeof $$render<T>>['props'];
|
|
11
|
+
events(): ReturnType<typeof $$render<T>>['events'];
|
|
12
|
+
slots(): ReturnType<typeof $$render<T>>['slots'];
|
|
13
|
+
bindings(): "";
|
|
14
|
+
exports(): {};
|
|
15
|
+
}
|
|
16
|
+
interface $$IsomorphicComponent {
|
|
17
|
+
new <T>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<T>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<T>['props']>, ReturnType<__sveltets_Render<T>['events']>, ReturnType<__sveltets_Render<T>['slots']>> & {
|
|
18
|
+
$$bindings?: ReturnType<__sveltets_Render<T>['bindings']>;
|
|
19
|
+
} & ReturnType<__sveltets_Render<T>['exports']>;
|
|
20
|
+
<T>(internal: unknown, props: ReturnType<__sveltets_Render<T>['props']> & {}): ReturnType<__sveltets_Render<T>['exports']>;
|
|
21
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any>['bindings']>;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* A single-select group of large, clickable cards — each an optional leading
|
|
25
|
+
* icon, a label, and optional helper text. Use it instead of a `SingleSelect`
|
|
26
|
+
* when the choices benefit from a sentence of explanation (e.g. picking a
|
|
27
|
+
* report's delivery method or output format).
|
|
28
|
+
*
|
|
29
|
+
* Controlled: pass `selected` and update it in `onchange`. Accessible as a
|
|
30
|
+
* native radio group (the radio inputs are visually hidden but focusable).
|
|
31
|
+
*/
|
|
32
|
+
declare const OptionCards: $$IsomorphicComponent;
|
|
33
|
+
type OptionCards<T> = InstanceType<typeof OptionCards<T>>;
|
|
34
|
+
export default OptionCards;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { OptionCard } from '../Types/Internal/OptionCard.js';
|
|
2
|
+
/**
|
|
3
|
+
* Props for {@link OptionCards} — a single-select group of large, clickable
|
|
4
|
+
* cards (icon + label + helper), used when a choice benefits from more
|
|
5
|
+
* explanation than a plain `SingleSelect` (e.g. a delivery/format chooser).
|
|
6
|
+
*
|
|
7
|
+
* Controlled component: pass `selected` and update it from `onchange`.
|
|
8
|
+
* `T` is compared with `===`; use a primitive or a stable reference.
|
|
9
|
+
*/
|
|
10
|
+
export interface OptionCardsProps<T> {
|
|
11
|
+
/** `name` attribute shared by the underlying radio inputs. */
|
|
12
|
+
name?: string;
|
|
13
|
+
/** The option set rendered as cards. */
|
|
14
|
+
options: ReadonlyArray<OptionCard<T>>;
|
|
15
|
+
/** Currently-selected value. */
|
|
16
|
+
selected?: T;
|
|
17
|
+
/** Called when a card is chosen. May be `void` or `Promise<void>`. */
|
|
18
|
+
onchange?: (value: T) => void | Promise<void>;
|
|
19
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { icons } from '../../Components/Icons.js';
|
|
2
|
+
/**
|
|
3
|
+
* A single option in an {@link OptionCards} picker — a selectable card with
|
|
4
|
+
* an optional leading icon, a label, and optional helper text. The generic
|
|
5
|
+
* carries the concrete value type so the surrounding component stays
|
|
6
|
+
* type-safe in its `onchange` callback.
|
|
7
|
+
*/
|
|
8
|
+
export interface OptionCard<T> {
|
|
9
|
+
/** The option's value when selected (compared with `===`). */
|
|
10
|
+
value: T;
|
|
11
|
+
/** Visible card title. */
|
|
12
|
+
label: string;
|
|
13
|
+
/** Optional helper text under the title. */
|
|
14
|
+
info?: string;
|
|
15
|
+
/** Optional leading icon, looked up in the frozen icon registry. */
|
|
16
|
+
icon?: keyof typeof icons;
|
|
17
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/index.d.ts
CHANGED
|
@@ -11,6 +11,8 @@ export { default as Pagination } from './Components/Base/Pagination.svelte';
|
|
|
11
11
|
export { type PaginationProps } from './Components/Base/PaginationProps.js';
|
|
12
12
|
export { default as BigRadioSet } from './Components/BigRadioSet.svelte';
|
|
13
13
|
export type { BigRadioSetProps } from './Components/BigRadioSetProps.js';
|
|
14
|
+
export { default as OptionCards } from './Components/OptionCards.svelte';
|
|
15
|
+
export type { OptionCardsProps } from './Components/OptionCardsProps.js';
|
|
14
16
|
export { default as Bubble } from './Components/Bubble.svelte';
|
|
15
17
|
export { type BubbleColour } from './Components/BubbleColour.js';
|
|
16
18
|
export { type BubbleProps } from './Components/BubbleProps.js';
|
|
@@ -187,6 +189,7 @@ export { type UseTooltipHandlers, type UseTooltipOptions, useTooltip, } from './
|
|
|
187
189
|
export { Colour, ColourSet } from './scss/colours.js';
|
|
188
190
|
export { Sizing } from './scss/sizing.js';
|
|
189
191
|
export { type BigRadioOption } from './Types/Internal/BigRadioOption.js';
|
|
192
|
+
export { type OptionCard } from './Types/Internal/OptionCard.js';
|
|
190
193
|
export { type ButtonProp } from './Types/Internal/ButtonProp.js';
|
|
191
194
|
export { type CallbackButton } from './Types/Internal/CallbackButton.js';
|
|
192
195
|
export { type DateChange } from './Types/Internal/DateChange.js';
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export {} from './Components/Base/ContextWrapperProps.js';
|
|
|
7
7
|
export { default as Pagination } from './Components/Base/Pagination.svelte';
|
|
8
8
|
export {} from './Components/Base/PaginationProps.js';
|
|
9
9
|
export { default as BigRadioSet } from './Components/BigRadioSet.svelte';
|
|
10
|
+
export { default as OptionCards } from './Components/OptionCards.svelte';
|
|
10
11
|
export { default as Bubble } from './Components/Bubble.svelte';
|
|
11
12
|
export {} from './Components/BubbleColour.js';
|
|
12
13
|
export {} from './Components/BubbleProps.js';
|
|
@@ -146,6 +147,7 @@ export { useTooltip, } from './Helpers/useTooltip.svelte.js';
|
|
|
146
147
|
export { Colour, ColourSet } from './scss/colours.js';
|
|
147
148
|
export { Sizing } from './scss/sizing.js';
|
|
148
149
|
export {} from './Types/Internal/BigRadioOption.js';
|
|
150
|
+
export {} from './Types/Internal/OptionCard.js';
|
|
149
151
|
export {} from './Types/Internal/ButtonProp.js';
|
|
150
152
|
export {} from './Types/Internal/CallbackButton.js';
|
|
151
153
|
export {} from './Types/Internal/DateChange.js';
|