@lavalogic/scoria 0.39.2 → 0.40.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 +58 -58
- package/dist/Components/AccordionGroup.svelte +46 -46
- package/dist/Components/AccordionGroupButton.svelte +76 -76
- package/dist/Components/Action.svelte +136 -136
- package/dist/Components/AlertModal.svelte +195 -195
- package/dist/Components/AppointmentCalendar/AppointmentCalendar.svelte +729 -729
- package/dist/Components/Base/BaseModal.svelte +125 -125
- package/dist/Components/Base/ContextWrapper.svelte +72 -72
- package/dist/Components/Base/Pagination.svelte +198 -198
- package/dist/Components/Base/Snippets.svelte +36 -36
- package/dist/Components/BigRadioSet.svelte +38 -38
- package/dist/Components/Bubble.svelte +101 -101
- package/dist/Components/Button.svelte +209 -209
- package/dist/Components/Checkbox.svelte +86 -86
- package/dist/Components/CollapsibleCard.svelte +78 -78
- package/dist/Components/ConditionBuilder/ConditionBuilder.svelte +212 -0
- package/dist/Components/ConditionBuilder/ConditionBuilder.svelte.d.ts +25 -0
- package/dist/Components/ConditionBuilder/ConditionBuilderProps.d.ts +45 -0
- package/dist/Components/ConditionBuilder/ConditionBuilderProps.js +1 -0
- package/dist/Components/ConditionBuilder/ConditionTree.d.ts +27 -0
- package/dist/Components/ConditionBuilder/ConditionTree.js +9 -0
- package/dist/Components/Contexts/ContextMenu.svelte +164 -164
- package/dist/Components/Contexts/ContextMenuDivider.svelte +15 -15
- package/dist/Components/Contexts/ContextMenuOption.svelte +60 -60
- package/dist/Components/Contexts/Toast.svelte +86 -86
- package/dist/Components/Contexts/ToastContainer.svelte +65 -65
- package/dist/Components/Contexts/Tooltip.svelte +37 -37
- package/dist/Components/DataMatrixIcon.svelte +112 -112
- package/dist/Components/DateInput.svelte +148 -148
- package/dist/Components/DatePicker.svelte +300 -300
- package/dist/Components/DesktopModal.svelte +90 -90
- package/dist/Components/Dial.svelte +204 -204
- package/dist/Components/DimensionInput.svelte +170 -170
- package/dist/Components/DragMenu/DragMenuHolder.svelte +119 -119
- package/dist/Components/DragMenu/DraggableCard.svelte +77 -77
- package/dist/Components/FileCard.svelte +24 -24
- package/dist/Components/FileUpload.svelte +236 -236
- package/dist/Components/GridInput.svelte +196 -196
- package/dist/Components/GridInputSet.svelte +29 -29
- package/dist/Components/HorizontalTabGroup.svelte +82 -82
- package/dist/Components/HorizontalTabGroupButton.svelte +44 -44
- package/dist/Components/Icon.svelte +128 -128
- package/dist/Components/Icons.js +357 -357
- package/dist/Components/InfoAlert.svelte +35 -35
- package/dist/Components/LoadingAnimation.svelte +29 -29
- package/dist/Components/LoadingModal.svelte +45 -45
- package/dist/Components/LoadingOverlay.svelte +25 -25
- package/dist/Components/Modal.svelte +258 -258
- package/dist/Components/MultiSelect.svelte +220 -220
- package/dist/Components/Nav/Nav.svelte +110 -110
- package/dist/Components/Nav/NavServiceMenuList.svelte +43 -43
- package/dist/Components/Nav/NavTab.svelte +62 -62
- package/dist/Components/Nav/ServiceMenuItem.svelte +112 -112
- package/dist/Components/Nav/ServicesNav.svelte +80 -80
- package/dist/Components/NumberInput.svelte +157 -157
- package/dist/Components/PageHeading.svelte +25 -25
- package/dist/Components/PasswordInput.svelte +88 -88
- package/dist/Components/Portal.svelte +36 -36
- package/dist/Components/ProgressBubble.svelte +107 -107
- package/dist/Components/QuerySelect.svelte +366 -366
- package/dist/Components/SingleSelect.svelte +250 -250
- package/dist/Components/StepButton.svelte +70 -70
- package/dist/Components/StepForm.svelte +140 -140
- package/dist/Components/Switch.svelte +69 -69
- package/dist/Components/Table/ARCHITECTURE.md +298 -298
- package/dist/Components/Table/Body/QuickSearchCell.svelte +679 -679
- package/dist/Components/Table/Body/Rows/ColumnHighlight.svelte +51 -51
- package/dist/Components/Table/Body/Rows/ColumnList.svelte +59 -59
- package/dist/Components/Table/Body/Rows/ColumnListRow.svelte +454 -454
- package/dist/Components/Table/Body/Rows/Columns/AccessorComponent.svelte +79 -79
- package/dist/Components/Table/Body/Rows/Columns/ActionsCell.svelte +185 -185
- package/dist/Components/Table/Body/Rows/Columns/BubbleCell.svelte +124 -124
- package/dist/Components/Table/Body/Rows/Columns/ExpandCell.svelte +120 -120
- package/dist/Components/Table/Body/Rows/Columns/FocusableImmutableCell.svelte +234 -234
- package/dist/Components/Table/Body/Rows/Columns/ProgressCell.svelte +105 -105
- package/dist/Components/Table/Body/Rows/Columns/TableAction.svelte +87 -87
- package/dist/Components/Table/Body/Rows/Columns/TableCheckbox.svelte +126 -126
- package/dist/Components/Table/Body/Rows/Columns/TableColumn.svelte +159 -159
- package/dist/Components/Table/Body/Rows/Columns/TableDatePicker.svelte +246 -246
- package/dist/Components/Table/Body/Rows/Columns/TableNumberInput.svelte +216 -216
- package/dist/Components/Table/Body/Rows/Columns/TableQuerySelect.svelte +252 -252
- package/dist/Components/Table/Body/Rows/Columns/TableRowSelectionCheckbox.svelte +179 -179
- package/dist/Components/Table/Body/Rows/Columns/TableSelect.svelte +221 -221
- package/dist/Components/Table/Body/Rows/Columns/TableTextInput.svelte +197 -197
- package/dist/Components/Table/Body/Rows/Columns/ValidityCell.svelte +190 -190
- package/dist/Components/Table/Body/Rows/TableRow.svelte +290 -290
- package/dist/Components/Table/Body/TableBody.svelte +155 -155
- package/dist/Components/Table/Headers/HighlightAllHeader.svelte +41 -41
- package/dist/Components/Table/Headers/SelectAllHeader.svelte +30 -30
- package/dist/Components/Table/Headers/TableHead.svelte +415 -415
- package/dist/Components/Table/Misc/ColumnPanel.svelte +39 -39
- package/dist/Components/Table/Misc/ColumnPanelModal.svelte +39 -39
- package/dist/Components/Table/Misc/FilterInput.svelte +641 -641
- package/dist/Components/Table/Misc/FilterPanel.svelte +190 -190
- package/dist/Components/Table/Misc/FilterPanelModal.svelte +31 -31
- package/dist/Components/Table/Misc/ShareViewModal.svelte +291 -291
- package/dist/Components/Table/Misc/SidePanel.svelte +35 -35
- package/dist/Components/Table/Misc/TableConfigurationModal.svelte +644 -644
- package/dist/Components/Table/Misc/TableFooter.svelte +340 -340
- package/dist/Components/Table/Misc/TableHorizontalBar.svelte +140 -140
- package/dist/Components/Table/Misc/TableSidebar.svelte +200 -200
- package/dist/Components/Table/Misc/TableViewDropdown.svelte +105 -105
- package/dist/Components/Table/Misc/ToolboxPanel.svelte +100 -100
- package/dist/Components/Table/Misc/ToolboxPanelModal.svelte +107 -107
- package/dist/Components/Table/Misc/UpdateViewOptionsModal.svelte +192 -192
- package/dist/Components/Table/NestedTable.svelte +130 -130
- package/dist/Components/Table/Table.svelte +692 -692
- package/dist/Components/Test/TestContextConsumer.svelte +13 -13
- package/dist/Components/TextArea.svelte +130 -130
- package/dist/Components/TextInput.svelte +176 -176
- package/dist/Components/ThreeStateRadio.svelte +131 -131
- package/dist/Components/Touch/BoolCard.svelte +45 -45
- package/dist/Components/Touch/DateModal.svelte +209 -209
- package/dist/Components/Touch/EditCard.svelte +59 -59
- package/dist/Components/Touch/InfoCard.svelte +31 -31
- package/dist/Components/Touch/InfoTextCard.svelte +28 -28
- package/dist/Components/Touch/ModalExplanation.svelte +17 -17
- package/dist/Components/Touch/NumberKeyboard.svelte +225 -225
- package/dist/Components/Touch/NumberModal.svelte +79 -79
- package/dist/Components/Touch/PlusMinusCard.svelte +46 -46
- package/dist/Components/Touch/SelectModal.svelte +127 -127
- package/dist/Components/Touch/SummaryCard.svelte +93 -93
- package/dist/Components/Touch/TextAreaModal.svelte +95 -95
- package/dist/Components/Touch/TextModal.svelte +106 -106
- package/dist/Components/Touch/TouchCard.svelte +33 -33
- package/dist/Components/Touch/TouchModal.svelte +274 -274
- package/dist/Components/Touch/UtilityButton.svelte +109 -109
- package/dist/Components/VerticalTabGroup.svelte +79 -79
- package/dist/Components/VerticalTabGroupButton.svelte +58 -58
- package/dist/Helpers/Datamatrix.d.ts +19 -19
- package/dist/Helpers/Datamatrix.js +291 -291
- package/dist/Types/Examples/ExampleModal.svelte +35 -35
- package/dist/index.d.ts +3 -0
- package/dist/index.js +2 -0
- package/dist/scss/_basics.scss +12 -12
- package/dist/scss/_colours.scss +134 -134
- package/dist/scss/_mixins.scss +3392 -3392
- package/dist/scss/_motion.scss +57 -57
- package/dist/scss/_sizing.scss +85 -85
- package/dist/scss/_transitions.scss +8 -8
- package/package.json +1 -1
|
@@ -1,88 +1,88 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script
|
|
4
|
-
lang="ts"
|
|
5
|
-
module
|
|
6
|
-
>
|
|
7
|
-
import { generateWeakId } from '../Helpers/Helpers.svelte.js';
|
|
8
|
-
import { Size } from '../Types/Internal/Size.js';
|
|
9
|
-
import type { CheckboxProps } from './CheckboxProps.js';
|
|
10
|
-
import Icon from './Icon.svelte';
|
|
11
|
-
</script>
|
|
12
|
-
|
|
13
|
-
<script lang="ts">
|
|
14
|
-
let {
|
|
15
|
-
value = false,
|
|
16
|
-
id = generateWeakId(),
|
|
17
|
-
icon,
|
|
18
|
-
size,
|
|
19
|
-
label,
|
|
20
|
-
disabled,
|
|
21
|
-
onchange,
|
|
22
|
-
}: CheckboxProps = $props();
|
|
23
|
-
</script>
|
|
24
|
-
|
|
25
|
-
{#if icon}
|
|
26
|
-
<div
|
|
27
|
-
class="outer-checkbox-container"
|
|
28
|
-
class:fill-width={size === Size.FillWidth}
|
|
29
|
-
class:fill-height={size === Size.FillHeight}
|
|
30
|
-
>
|
|
31
|
-
<div
|
|
32
|
-
class="inner-checkbox-container with-icon"
|
|
33
|
-
class:disabled
|
|
34
|
-
>
|
|
35
|
-
<input
|
|
36
|
-
{id}
|
|
37
|
-
name={id}
|
|
38
|
-
class="with-icon"
|
|
39
|
-
{onchange}
|
|
40
|
-
type="checkbox"
|
|
41
|
-
{disabled}
|
|
42
|
-
checked={value}
|
|
43
|
-
/>
|
|
44
|
-
<label
|
|
45
|
-
class="icon-label"
|
|
46
|
-
for={id}
|
|
47
|
-
class:disabled
|
|
48
|
-
>
|
|
49
|
-
<Icon
|
|
50
|
-
{...icon}
|
|
51
|
-
size={icon.size ?? size ?? Size.DoubleXLarge}
|
|
52
|
-
/>
|
|
53
|
-
</label>
|
|
54
|
-
</div>
|
|
55
|
-
{#if label}
|
|
56
|
-
<label
|
|
57
|
-
class="text-label"
|
|
58
|
-
for={id}>{label}</label
|
|
59
|
-
>
|
|
60
|
-
{/if}
|
|
61
|
-
</div>
|
|
62
|
-
{:else}
|
|
63
|
-
<div
|
|
64
|
-
class="checkbox-container"
|
|
65
|
-
class:compact={size === Size.Tiny ||
|
|
66
|
-
size === Size.Small ||
|
|
67
|
-
size === Size.MediumSmall ||
|
|
68
|
-
size === Size.Medium}
|
|
69
|
-
>
|
|
70
|
-
<input
|
|
71
|
-
{id}
|
|
72
|
-
{onchange}
|
|
73
|
-
type="checkbox"
|
|
74
|
-
checked={value}
|
|
75
|
-
{disabled}
|
|
76
|
-
/>
|
|
77
|
-
{#if label}
|
|
78
|
-
<label
|
|
79
|
-
class="text-label"
|
|
80
|
-
for={id}>{label}</label
|
|
81
|
-
>
|
|
82
|
-
{/if}
|
|
83
|
-
</div>
|
|
84
|
-
{/if}
|
|
85
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
module
|
|
6
|
+
>
|
|
7
|
+
import { generateWeakId } from '../Helpers/Helpers.svelte.js';
|
|
8
|
+
import { Size } from '../Types/Internal/Size.js';
|
|
9
|
+
import type { CheckboxProps } from './CheckboxProps.js';
|
|
10
|
+
import Icon from './Icon.svelte';
|
|
11
|
+
</script>
|
|
12
|
+
|
|
13
|
+
<script lang="ts">
|
|
14
|
+
let {
|
|
15
|
+
value = false,
|
|
16
|
+
id = generateWeakId(),
|
|
17
|
+
icon,
|
|
18
|
+
size,
|
|
19
|
+
label,
|
|
20
|
+
disabled,
|
|
21
|
+
onchange,
|
|
22
|
+
}: CheckboxProps = $props();
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
{#if icon}
|
|
26
|
+
<div
|
|
27
|
+
class="outer-checkbox-container"
|
|
28
|
+
class:fill-width={size === Size.FillWidth}
|
|
29
|
+
class:fill-height={size === Size.FillHeight}
|
|
30
|
+
>
|
|
31
|
+
<div
|
|
32
|
+
class="inner-checkbox-container with-icon"
|
|
33
|
+
class:disabled
|
|
34
|
+
>
|
|
35
|
+
<input
|
|
36
|
+
{id}
|
|
37
|
+
name={id}
|
|
38
|
+
class="with-icon"
|
|
39
|
+
{onchange}
|
|
40
|
+
type="checkbox"
|
|
41
|
+
{disabled}
|
|
42
|
+
checked={value}
|
|
43
|
+
/>
|
|
44
|
+
<label
|
|
45
|
+
class="icon-label"
|
|
46
|
+
for={id}
|
|
47
|
+
class:disabled
|
|
48
|
+
>
|
|
49
|
+
<Icon
|
|
50
|
+
{...icon}
|
|
51
|
+
size={icon.size ?? size ?? Size.DoubleXLarge}
|
|
52
|
+
/>
|
|
53
|
+
</label>
|
|
54
|
+
</div>
|
|
55
|
+
{#if label}
|
|
56
|
+
<label
|
|
57
|
+
class="text-label"
|
|
58
|
+
for={id}>{label}</label
|
|
59
|
+
>
|
|
60
|
+
{/if}
|
|
61
|
+
</div>
|
|
62
|
+
{:else}
|
|
63
|
+
<div
|
|
64
|
+
class="checkbox-container"
|
|
65
|
+
class:compact={size === Size.Tiny ||
|
|
66
|
+
size === Size.Small ||
|
|
67
|
+
size === Size.MediumSmall ||
|
|
68
|
+
size === Size.Medium}
|
|
69
|
+
>
|
|
70
|
+
<input
|
|
71
|
+
{id}
|
|
72
|
+
{onchange}
|
|
73
|
+
type="checkbox"
|
|
74
|
+
checked={value}
|
|
75
|
+
{disabled}
|
|
76
|
+
/>
|
|
77
|
+
{#if label}
|
|
78
|
+
<label
|
|
79
|
+
class="text-label"
|
|
80
|
+
for={id}>{label}</label
|
|
81
|
+
>
|
|
82
|
+
{/if}
|
|
83
|
+
</div>
|
|
84
|
+
{/if}
|
|
85
|
+
|
|
86
86
|
<style>.outer-checkbox-container {
|
|
87
87
|
box-sizing: border-box;
|
|
88
88
|
display: flex;
|
|
@@ -176,4 +176,4 @@ label {
|
|
|
176
176
|
display: block;
|
|
177
177
|
cursor: pointer;
|
|
178
178
|
position: relative;
|
|
179
|
-
}</style>
|
|
179
|
+
}</style>
|
|
@@ -1,80 +1,80 @@
|
|
|
1
|
-
<svelte:options runes />
|
|
2
|
-
|
|
3
|
-
<script
|
|
4
|
-
lang="ts"
|
|
5
|
-
module
|
|
6
|
-
>
|
|
7
|
-
import { generateWeakId } from '../Helpers/Helpers.svelte.js';
|
|
8
|
-
</script>
|
|
9
|
-
|
|
10
|
-
<script lang="ts">
|
|
11
|
-
import { loadingText } from '../Helpers/Helpers.svelte.js';
|
|
12
|
-
import { Size } from '../Types/Internal/Size.js';
|
|
13
|
-
import { Colour } from '../scss/colours.js';
|
|
14
|
-
import Action from './Action.svelte';
|
|
15
|
-
import type { CollapsibleCardProps } from './CollapsibleCardProps.js';
|
|
16
|
-
|
|
17
|
-
let {
|
|
18
|
-
title,
|
|
19
|
-
subtitle,
|
|
20
|
-
maxHeight,
|
|
21
|
-
children,
|
|
22
|
-
grow,
|
|
23
|
-
isCollapsed = $bindable(false),
|
|
24
|
-
}: CollapsibleCardProps = $props();
|
|
25
|
-
|
|
26
|
-
const contentId = `collapsible-card-${generateWeakId()}`;
|
|
27
|
-
|
|
28
|
-
const cardMaxHeight = $derived(maxHeight != null && maxHeight > 0 ? `${maxHeight}px` : undefined);
|
|
29
|
-
</script>
|
|
30
|
-
|
|
31
|
-
<div
|
|
32
|
-
class="collapsible-card"
|
|
33
|
-
style={cardMaxHeight != null ? `--card-max-height: ${cardMaxHeight};` : undefined}
|
|
34
|
-
class:is-collapsed={isCollapsed}
|
|
35
|
-
class:grow
|
|
36
|
-
>
|
|
37
|
-
<div class="heading">
|
|
38
|
-
<div class="left">
|
|
39
|
-
<h3>{title}</h3>
|
|
40
|
-
{#if subtitle}
|
|
41
|
-
{#await subtitle}
|
|
42
|
-
<span>{loadingText}</span>
|
|
43
|
-
{:then resolvedSubtitle}
|
|
44
|
-
<span>{resolvedSubtitle}</span>
|
|
45
|
-
{/await}
|
|
46
|
-
{/if}
|
|
47
|
-
</div>
|
|
48
|
-
<div class="right">
|
|
49
|
-
<Action
|
|
50
|
-
label={isCollapsed ? 'Expand' : 'Collapse'}
|
|
51
|
-
aria-expanded={!isCollapsed}
|
|
52
|
-
aria-controls={contentId}
|
|
53
|
-
onclick={() => {
|
|
54
|
-
isCollapsed = !isCollapsed;
|
|
55
|
-
}}
|
|
56
|
-
size={Size.TripleXLarge}
|
|
57
|
-
icon={{
|
|
58
|
-
name: isCollapsed ? 'circle-plus' : 'circle-minus',
|
|
59
|
-
colour: Colour['$ui-blue-5'],
|
|
60
|
-
size: Size.Medium,
|
|
61
|
-
}}
|
|
62
|
-
/>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
|
|
66
|
-
<div
|
|
67
|
-
id={contentId}
|
|
68
|
-
class="content"
|
|
69
|
-
class:is-collapsed={isCollapsed}
|
|
70
|
-
aria-hidden={isCollapsed}
|
|
71
|
-
>
|
|
72
|
-
{#if children}
|
|
73
|
-
{@render children()}
|
|
74
|
-
{/if}
|
|
75
|
-
</div>
|
|
76
|
-
</div>
|
|
77
|
-
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
module
|
|
6
|
+
>
|
|
7
|
+
import { generateWeakId } from '../Helpers/Helpers.svelte.js';
|
|
8
|
+
</script>
|
|
9
|
+
|
|
10
|
+
<script lang="ts">
|
|
11
|
+
import { loadingText } from '../Helpers/Helpers.svelte.js';
|
|
12
|
+
import { Size } from '../Types/Internal/Size.js';
|
|
13
|
+
import { Colour } from '../scss/colours.js';
|
|
14
|
+
import Action from './Action.svelte';
|
|
15
|
+
import type { CollapsibleCardProps } from './CollapsibleCardProps.js';
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
title,
|
|
19
|
+
subtitle,
|
|
20
|
+
maxHeight,
|
|
21
|
+
children,
|
|
22
|
+
grow,
|
|
23
|
+
isCollapsed = $bindable(false),
|
|
24
|
+
}: CollapsibleCardProps = $props();
|
|
25
|
+
|
|
26
|
+
const contentId = `collapsible-card-${generateWeakId()}`;
|
|
27
|
+
|
|
28
|
+
const cardMaxHeight = $derived(maxHeight != null && maxHeight > 0 ? `${maxHeight}px` : undefined);
|
|
29
|
+
</script>
|
|
30
|
+
|
|
31
|
+
<div
|
|
32
|
+
class="collapsible-card"
|
|
33
|
+
style={cardMaxHeight != null ? `--card-max-height: ${cardMaxHeight};` : undefined}
|
|
34
|
+
class:is-collapsed={isCollapsed}
|
|
35
|
+
class:grow
|
|
36
|
+
>
|
|
37
|
+
<div class="heading">
|
|
38
|
+
<div class="left">
|
|
39
|
+
<h3>{title}</h3>
|
|
40
|
+
{#if subtitle}
|
|
41
|
+
{#await subtitle}
|
|
42
|
+
<span>{loadingText}</span>
|
|
43
|
+
{:then resolvedSubtitle}
|
|
44
|
+
<span>{resolvedSubtitle}</span>
|
|
45
|
+
{/await}
|
|
46
|
+
{/if}
|
|
47
|
+
</div>
|
|
48
|
+
<div class="right">
|
|
49
|
+
<Action
|
|
50
|
+
label={isCollapsed ? 'Expand' : 'Collapse'}
|
|
51
|
+
aria-expanded={!isCollapsed}
|
|
52
|
+
aria-controls={contentId}
|
|
53
|
+
onclick={() => {
|
|
54
|
+
isCollapsed = !isCollapsed;
|
|
55
|
+
}}
|
|
56
|
+
size={Size.TripleXLarge}
|
|
57
|
+
icon={{
|
|
58
|
+
name: isCollapsed ? 'circle-plus' : 'circle-minus',
|
|
59
|
+
colour: Colour['$ui-blue-5'],
|
|
60
|
+
size: Size.Medium,
|
|
61
|
+
}}
|
|
62
|
+
/>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
|
|
66
|
+
<div
|
|
67
|
+
id={contentId}
|
|
68
|
+
class="content"
|
|
69
|
+
class:is-collapsed={isCollapsed}
|
|
70
|
+
aria-hidden={isCollapsed}
|
|
71
|
+
>
|
|
72
|
+
{#if children}
|
|
73
|
+
{@render children()}
|
|
74
|
+
{/if}
|
|
75
|
+
</div>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
78
|
<style>.collapsible-card {
|
|
79
79
|
background-color: #ffffff;
|
|
80
80
|
display: flex;
|
|
@@ -170,4 +170,4 @@ div.content.is-collapsed {
|
|
|
170
170
|
animation-duration: 0.001ms !important;
|
|
171
171
|
transition-duration: 0.001ms !important;
|
|
172
172
|
}
|
|
173
|
-
}</style>
|
|
173
|
+
}</style>
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
<svelte:options runes />
|
|
2
|
+
|
|
3
|
+
<script
|
|
4
|
+
lang="ts"
|
|
5
|
+
generics="F extends string | number, O extends string | number, V"
|
|
6
|
+
>
|
|
7
|
+
import SingleSelect from '../SingleSelect.svelte';
|
|
8
|
+
import Button from '../Button.svelte';
|
|
9
|
+
import type { ConditionBuilderProps } from './ConditionBuilderProps.js';
|
|
10
|
+
import { makeGroup, makeLeaf, type ConditionLeaf, type ConditionNode } from './ConditionTree.js';
|
|
11
|
+
import Self from './ConditionBuilder.svelte';
|
|
12
|
+
|
|
13
|
+
const {
|
|
14
|
+
root,
|
|
15
|
+
onChange,
|
|
16
|
+
fields,
|
|
17
|
+
operatorsFor,
|
|
18
|
+
valueEditor,
|
|
19
|
+
defaultValueFor,
|
|
20
|
+
allowGroups = true,
|
|
21
|
+
maxDepth = 5,
|
|
22
|
+
addConditionLabel = 'Add Condition',
|
|
23
|
+
addGroupLabel = 'Add Group',
|
|
24
|
+
andLabel = 'AND',
|
|
25
|
+
orLabel = 'OR',
|
|
26
|
+
depth = 0,
|
|
27
|
+
}: ConditionBuilderProps<F, O, V> = $props();
|
|
28
|
+
|
|
29
|
+
function seedValue(field: F | null, operator: O | null): V {
|
|
30
|
+
return defaultValueFor ? defaultValueFor(field, operator) : (null as V);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function setCombinator(combinator: 'and' | 'or') {
|
|
34
|
+
root.combinator = combinator;
|
|
35
|
+
onChange(root);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function addLeaf() {
|
|
39
|
+
root.children.push(makeLeaf<F, O, V>(seedValue(null, null)));
|
|
40
|
+
onChange(root);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function addGroup() {
|
|
44
|
+
root.children.push(makeGroup<F, O, V>());
|
|
45
|
+
onChange(root);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function removeChild(node: ConditionNode<F, O, V>) {
|
|
49
|
+
root.children = root.children.filter((child) => child.id !== node.id);
|
|
50
|
+
onChange(root);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function setField(leaf: ConditionLeaf<F, O, V>, field: F | null) {
|
|
54
|
+
leaf.field = field;
|
|
55
|
+
leaf.operator = null;
|
|
56
|
+
leaf.value = seedValue(field, null);
|
|
57
|
+
onChange(root);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function setOperator(leaf: ConditionLeaf<F, O, V>, operator: O | null) {
|
|
61
|
+
leaf.operator = operator;
|
|
62
|
+
leaf.value = seedValue(leaf.field, operator);
|
|
63
|
+
onChange(root);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function setValue(leaf: ConditionLeaf<F, O, V>, value: V) {
|
|
67
|
+
leaf.value = value;
|
|
68
|
+
onChange(root);
|
|
69
|
+
}
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<div
|
|
73
|
+
class="group"
|
|
74
|
+
class:nested={depth > 0}
|
|
75
|
+
>
|
|
76
|
+
<div class="combinator">
|
|
77
|
+
<Button
|
|
78
|
+
label={andLabel}
|
|
79
|
+
toggled={root.combinator === 'and'}
|
|
80
|
+
onclick={() => setCombinator('and')}>{andLabel}</Button
|
|
81
|
+
>
|
|
82
|
+
<Button
|
|
83
|
+
label={orLabel}
|
|
84
|
+
toggled={root.combinator === 'or'}
|
|
85
|
+
onclick={() => setCombinator('or')}>{orLabel}</Button
|
|
86
|
+
>
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<div class="children">
|
|
90
|
+
{#each root.children as child (child.id)}
|
|
91
|
+
{#if child.kind === 'leaf'}
|
|
92
|
+
<div class="leaf">
|
|
93
|
+
<SingleSelect
|
|
94
|
+
label="Field"
|
|
95
|
+
options={[...fields]}
|
|
96
|
+
labelProp="label"
|
|
97
|
+
valueProp="value"
|
|
98
|
+
valueAsObject={false}
|
|
99
|
+
clearable
|
|
100
|
+
value={child.field}
|
|
101
|
+
onchange={(value) => setField(child, value)}
|
|
102
|
+
/>
|
|
103
|
+
<SingleSelect
|
|
104
|
+
label="Operator"
|
|
105
|
+
options={[...operatorsFor(child.field)]}
|
|
106
|
+
labelProp="label"
|
|
107
|
+
valueProp="value"
|
|
108
|
+
valueAsObject={false}
|
|
109
|
+
clearable
|
|
110
|
+
value={child.operator}
|
|
111
|
+
onchange={(value) => setOperator(child, value)}
|
|
112
|
+
/>
|
|
113
|
+
<div class="value-editor">
|
|
114
|
+
{@render valueEditor(child, (value) => setValue(child, value))}
|
|
115
|
+
</div>
|
|
116
|
+
<Button
|
|
117
|
+
label="Remove condition"
|
|
118
|
+
iconLeft={{ name: 'circle-cross' }}
|
|
119
|
+
onclick={() => removeChild(child)}
|
|
120
|
+
/>
|
|
121
|
+
</div>
|
|
122
|
+
{:else}
|
|
123
|
+
<div class="subgroup">
|
|
124
|
+
<Self
|
|
125
|
+
root={child}
|
|
126
|
+
{onChange}
|
|
127
|
+
{fields}
|
|
128
|
+
{operatorsFor}
|
|
129
|
+
{valueEditor}
|
|
130
|
+
{defaultValueFor}
|
|
131
|
+
{allowGroups}
|
|
132
|
+
{maxDepth}
|
|
133
|
+
{addConditionLabel}
|
|
134
|
+
{addGroupLabel}
|
|
135
|
+
{andLabel}
|
|
136
|
+
{orLabel}
|
|
137
|
+
depth={depth + 1}
|
|
138
|
+
/>
|
|
139
|
+
<Button
|
|
140
|
+
label="Remove group"
|
|
141
|
+
iconLeft={{ name: 'circle-cross' }}
|
|
142
|
+
onclick={() => removeChild(child)}
|
|
143
|
+
/>
|
|
144
|
+
</div>
|
|
145
|
+
{/if}
|
|
146
|
+
{/each}
|
|
147
|
+
</div>
|
|
148
|
+
|
|
149
|
+
<div class="actions">
|
|
150
|
+
<Button
|
|
151
|
+
label={addConditionLabel}
|
|
152
|
+
iconLeft={{ name: 'circle-plus' }}
|
|
153
|
+
onclick={addLeaf}>{addConditionLabel}</Button
|
|
154
|
+
>
|
|
155
|
+
{#if allowGroups && depth < maxDepth}
|
|
156
|
+
<Button
|
|
157
|
+
label={addGroupLabel}
|
|
158
|
+
iconLeft={{ name: 'circle-plus' }}
|
|
159
|
+
onclick={addGroup}>{addGroupLabel}</Button
|
|
160
|
+
>
|
|
161
|
+
{/if}
|
|
162
|
+
</div>
|
|
163
|
+
</div>
|
|
164
|
+
|
|
165
|
+
<style>.group {
|
|
166
|
+
display: flex;
|
|
167
|
+
flex-flow: column nowrap;
|
|
168
|
+
gap: 0.5rem;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
.group.nested {
|
|
172
|
+
border: solid 1px #cbd4da;
|
|
173
|
+
padding: 0.5rem;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.combinator {
|
|
177
|
+
display: flex;
|
|
178
|
+
flex-flow: row nowrap;
|
|
179
|
+
gap: 0.5rem;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
.children {
|
|
183
|
+
display: flex;
|
|
184
|
+
flex-flow: column nowrap;
|
|
185
|
+
gap: 0.5rem;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.leaf {
|
|
189
|
+
display: flex;
|
|
190
|
+
flex-flow: row wrap;
|
|
191
|
+
align-items: center;
|
|
192
|
+
gap: 0.5rem;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.subgroup {
|
|
196
|
+
display: flex;
|
|
197
|
+
flex-flow: row nowrap;
|
|
198
|
+
align-items: flex-start;
|
|
199
|
+
gap: 0.5rem;
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
.value-editor {
|
|
203
|
+
display: flex;
|
|
204
|
+
flex-flow: row nowrap;
|
|
205
|
+
gap: 0.5rem;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
.actions {
|
|
209
|
+
display: flex;
|
|
210
|
+
flex-flow: row nowrap;
|
|
211
|
+
gap: 0.5rem;
|
|
212
|
+
}</style>
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { ConditionBuilderProps } from './ConditionBuilderProps.js';
|
|
2
|
+
declare function $$render<F extends string | number, O extends string | number, V>(): {
|
|
3
|
+
props: ConditionBuilderProps<F, O, V>;
|
|
4
|
+
exports: {};
|
|
5
|
+
bindings: "";
|
|
6
|
+
slots: {};
|
|
7
|
+
events: {};
|
|
8
|
+
};
|
|
9
|
+
declare class __sveltets_Render<F extends string | number, O extends string | number, V> {
|
|
10
|
+
props(): ReturnType<typeof $$render<F, O, V>>['props'];
|
|
11
|
+
events(): ReturnType<typeof $$render<F, O, V>>['events'];
|
|
12
|
+
slots(): ReturnType<typeof $$render<F, O, V>>['slots'];
|
|
13
|
+
bindings(): "";
|
|
14
|
+
exports(): {};
|
|
15
|
+
}
|
|
16
|
+
interface $$IsomorphicComponent {
|
|
17
|
+
new <F extends string | number, O extends string | number, V>(options: import('svelte').ComponentConstructorOptions<ReturnType<__sveltets_Render<F, O, V>['props']>>): import('svelte').SvelteComponent<ReturnType<__sveltets_Render<F, O, V>['props']>, ReturnType<__sveltets_Render<F, O, V>['events']>, ReturnType<__sveltets_Render<F, O, V>['slots']>> & {
|
|
18
|
+
$$bindings?: ReturnType<__sveltets_Render<F, O, V>['bindings']>;
|
|
19
|
+
} & ReturnType<__sveltets_Render<F, O, V>['exports']>;
|
|
20
|
+
<F extends string | number, O extends string | number, V>(internal: unknown, props: ReturnType<__sveltets_Render<F, O, V>['props']> & {}): ReturnType<__sveltets_Render<F, O, V>['exports']>;
|
|
21
|
+
z_$$bindings?: ReturnType<__sveltets_Render<any, any, any>['bindings']>;
|
|
22
|
+
}
|
|
23
|
+
declare const ConditionBuilder: $$IsomorphicComponent;
|
|
24
|
+
type ConditionBuilder<F extends string | number, O extends string | number, V> = InstanceType<typeof ConditionBuilder<F, O, V>>;
|
|
25
|
+
export default ConditionBuilder;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
import type { SelectOption } from '../../Types/Internal/SelectOption.js';
|
|
3
|
+
import type { ConditionGroup, ConditionLeaf } from './ConditionTree.js';
|
|
4
|
+
/**
|
|
5
|
+
* Props for {@link ConditionBuilder} — a generic, domain-free recursive
|
|
6
|
+
* AND/OR condition tree editor. The component owns only the tree shape and
|
|
7
|
+
* the combinator toggles; fields, operators and value editing are injected by
|
|
8
|
+
* the consumer so no SQL / query semantics leak into the library.
|
|
9
|
+
*
|
|
10
|
+
* `F`/`O` are the field-key and operator types (primitives so the internal
|
|
11
|
+
* dropdowns can use them as option values). `V` is the opaque value type,
|
|
12
|
+
* written exclusively through {@link ConditionBuilderProps.valueEditor}.
|
|
13
|
+
*/
|
|
14
|
+
export interface ConditionBuilderProps<F extends string | number, O extends string | number, V> {
|
|
15
|
+
/** The root group. Mutated in place; pair with `$state` in the consumer. */
|
|
16
|
+
root: ConditionGroup<F, O, V>;
|
|
17
|
+
/** Called after any structural or value change to the tree. */
|
|
18
|
+
onChange: (root: ConditionGroup<F, O, V>) => void;
|
|
19
|
+
/** Selectable fields for each leaf's field dropdown. */
|
|
20
|
+
fields: ReadonlyArray<SelectOption<F>>;
|
|
21
|
+
/** Operators valid for the chosen field (may vary by field/data type). */
|
|
22
|
+
operatorsFor: (field: F | null) => ReadonlyArray<SelectOption<O>>;
|
|
23
|
+
/**
|
|
24
|
+
* Renders the value input(s) for one leaf. Receives the leaf and a setter
|
|
25
|
+
* to write the new value back. This is how a consumer renders one input
|
|
26
|
+
* for "contains", two for "between", a multi-select for "in", etc.
|
|
27
|
+
*/
|
|
28
|
+
valueEditor: Snippet<[ConditionLeaf<F, O, V>, (value: V) => void]>;
|
|
29
|
+
/** Produces the value to seed when a leaf's field/operator changes. */
|
|
30
|
+
defaultValueFor?: (field: F | null, operator: O | null) => V;
|
|
31
|
+
/** Allow nested sub-groups. Defaults to true. */
|
|
32
|
+
allowGroups?: boolean;
|
|
33
|
+
/** Maximum nesting depth for sub-groups. Defaults to 5. */
|
|
34
|
+
maxDepth?: number;
|
|
35
|
+
/** Label for the add-condition button. Defaults to "Add Condition". */
|
|
36
|
+
addConditionLabel?: string;
|
|
37
|
+
/** Label for the add-group button. Defaults to "Add Group". */
|
|
38
|
+
addGroupLabel?: string;
|
|
39
|
+
/** Label for the AND toggle. Defaults to "AND". */
|
|
40
|
+
andLabel?: string;
|
|
41
|
+
/** Label for the OR toggle. Defaults to "OR". */
|
|
42
|
+
orLabel?: string;
|
|
43
|
+
/** Internal: current nesting depth. Consumers should not set this. */
|
|
44
|
+
depth?: number;
|
|
45
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** How a group combines its children. */
|
|
2
|
+
export type Combinator = 'and' | 'or';
|
|
3
|
+
/**
|
|
4
|
+
* A single condition: a (field, operator, value) triple. Generic over the
|
|
5
|
+
* field key `F`, operator `O` and value `V`. `value` is opaque to the
|
|
6
|
+
* builder — the consumer renders and writes it through the `valueEditor`
|
|
7
|
+
* snippet, so it can be a string, a tuple (e.g. for "between"), an array, etc.
|
|
8
|
+
*/
|
|
9
|
+
export interface ConditionLeaf<F, O, V> {
|
|
10
|
+
id: string;
|
|
11
|
+
kind: 'leaf';
|
|
12
|
+
field: F | null;
|
|
13
|
+
operator: O | null;
|
|
14
|
+
value: V;
|
|
15
|
+
}
|
|
16
|
+
/** A group of conditions combined with AND or OR. Groups may nest. */
|
|
17
|
+
export interface ConditionGroup<F, O, V> {
|
|
18
|
+
id: string;
|
|
19
|
+
kind: 'group';
|
|
20
|
+
combinator: Combinator;
|
|
21
|
+
children: Array<ConditionNode<F, O, V>>;
|
|
22
|
+
}
|
|
23
|
+
export type ConditionNode<F, O, V> = ConditionLeaf<F, O, V> | ConditionGroup<F, O, V>;
|
|
24
|
+
/** Construct a fresh leaf with a stable id. */
|
|
25
|
+
export declare function makeLeaf<F, O, V>(value: V, field?: F | null, operator?: O | null): ConditionLeaf<F, O, V>;
|
|
26
|
+
/** Construct a fresh group with a stable id. */
|
|
27
|
+
export declare function makeGroup<F, O, V>(combinator?: Combinator, children?: Array<ConditionNode<F, O, V>>): ConditionGroup<F, O, V>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { generateWeakId } from '../../Helpers/Helpers.svelte.js';
|
|
2
|
+
/** Construct a fresh leaf with a stable id. */
|
|
3
|
+
export function makeLeaf(value, field = null, operator = null) {
|
|
4
|
+
return { id: generateWeakId(), kind: 'leaf', field, operator, value };
|
|
5
|
+
}
|
|
6
|
+
/** Construct a fresh group with a stable id. */
|
|
7
|
+
export function makeGroup(combinator = 'and', children = []) {
|
|
8
|
+
return { id: generateWeakId(), kind: 'group', combinator, children };
|
|
9
|
+
}
|