@finsweet/webflow-apps-utils 1.0.2 → 1.0.3
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 +162 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/providers/GlobalProvider.mdx +322 -0
- package/dist/providers/GlobalProvider.svelte +58 -0
- package/dist/providers/GlobalProvider.svelte.d.ts +4 -0
- package/dist/providers/configuratorUtils.d.ts +37 -0
- package/dist/providers/configuratorUtils.js +219 -0
- package/dist/providers/globalContext.svelte.d.ts +18 -0
- package/dist/providers/globalContext.svelte.js +439 -0
- package/dist/providers/index.d.ts +5 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/types.d.ts +103 -0
- package/dist/providers/types.js +6 -0
- package/dist/router/README.md +2 -2
- package/dist/stores/index.d.ts +0 -1
- package/dist/stores/index.js +0 -1
- package/dist/types/webflow.d.ts +31 -47
- package/dist/ui/components/LoadingScreen.svelte +2 -1
- package/dist/ui/components/button/Button.svelte +1 -1
- package/dist/ui/components/button-group/ButtonGroup.stories.js +112 -0
- package/dist/ui/components/{ButtonGroup.svelte → button-group/ButtonGroup.svelte} +20 -33
- package/dist/ui/components/button-group/ButtonGroup.svelte.d.ts +13 -0
- package/dist/ui/components/button-group/index.d.ts +2 -0
- package/dist/ui/components/button-group/index.js +1 -0
- package/dist/ui/components/button-group/types.d.ts +32 -0
- package/dist/ui/components/checkbox/Checkbox.stories.d.ts +55 -0
- package/dist/ui/components/checkbox/Checkbox.stories.js +162 -0
- package/dist/ui/components/checkbox/Checkbox.svelte +141 -0
- package/dist/ui/components/checkbox/Checkbox.svelte.d.ts +4 -0
- package/dist/ui/components/checkbox/index.d.ts +2 -0
- package/dist/ui/components/checkbox/index.js +1 -0
- package/dist/ui/components/checkbox/types.d.ts +32 -0
- package/dist/ui/components/controlled-buttons/ControlledButtons.stories.d.ts +32 -0
- package/dist/ui/components/controlled-buttons/ControlledButtons.stories.js +152 -0
- package/dist/ui/components/{buttons/FooterButton.svelte → controlled-buttons/ControlledButtons.svelte} +18 -67
- package/dist/ui/components/controlled-buttons/ControlledButtons.svelte.d.ts +4 -0
- package/dist/ui/components/controlled-buttons/index.d.ts +2 -0
- package/dist/ui/components/controlled-buttons/index.js +1 -0
- package/dist/ui/components/{buttons → controlled-buttons}/types.d.ts +11 -4
- package/dist/ui/components/divider/Divider.stories.svelte +134 -0
- package/dist/ui/components/{clickable/Clickable.stories.svelte.d.ts → divider/Divider.stories.svelte.d.ts} +4 -4
- package/dist/ui/components/divider/Divider.svelte +30 -0
- package/dist/ui/components/divider/Divider.svelte.d.ts +4 -0
- package/dist/ui/components/divider/index.d.ts +2 -0
- package/dist/ui/components/divider/index.js +1 -0
- package/dist/ui/components/divider/types.d.ts +23 -0
- package/dist/ui/components/divider/types.js +1 -0
- package/dist/ui/components/iframe/Iframe.stories.svelte +122 -0
- package/dist/ui/components/{ToggleItem.svelte.d.ts → iframe/Iframe.stories.svelte.d.ts} +7 -8
- package/dist/ui/components/iframe/Iframe.svelte +75 -0
- package/dist/ui/components/iframe/Iframe.svelte.d.ts +4 -0
- package/dist/ui/components/iframe/index.d.ts +2 -0
- package/dist/ui/components/iframe/index.js +1 -0
- package/dist/ui/components/iframe/types.d.ts +38 -0
- package/dist/ui/components/iframe/types.js +1 -0
- package/dist/ui/components/index.d.ts +12 -39
- package/dist/ui/components/index.js +12 -39
- package/dist/ui/components/input/Input.stories.d.ts +24 -0
- package/dist/ui/components/input/Input.stories.js +98 -0
- package/dist/ui/components/input/Input.svelte +321 -80
- package/dist/ui/components/input/types.d.ts +27 -1
- package/dist/ui/components/layout/Layout.stories.svelte +3 -3
- package/dist/ui/components/layout/Layout.svelte +3 -5
- package/dist/ui/components/layout/common/EditModeMessage.svelte +24 -12
- package/dist/ui/components/layout/{ExampleLayout.svelte → examples/ExampleLayout.svelte} +34 -22
- package/dist/ui/components/layout/examples/Wrapper.svelte +9 -0
- package/dist/ui/components/{NoSettingsNeeded.svelte.d.ts → layout/examples/Wrapper.svelte.d.ts} +3 -3
- package/dist/ui/components/layout/examples/index.d.ts +2 -0
- package/dist/ui/components/layout/examples/index.js +2 -0
- package/dist/ui/components/layout/index.d.ts +2 -1
- package/dist/ui/components/layout/index.js +2 -1
- package/dist/ui/components/modal/Example.svelte +320 -0
- package/dist/ui/components/modal/Example.svelte.d.ts +3 -0
- package/dist/ui/components/modal/Modal.stories.svelte +18 -0
- package/dist/ui/components/modal/Modal.stories.svelte.d.ts +26 -0
- package/dist/ui/components/modal/Modal.svelte +490 -0
- package/dist/ui/components/modal/Modal.svelte.d.ts +130 -0
- package/dist/ui/components/modal/index.d.ts +2 -0
- package/dist/ui/components/modal/index.js +1 -0
- package/dist/ui/components/modal/types.d.ts +75 -0
- package/dist/ui/components/modal/types.js +1 -0
- package/dist/ui/components/notification/Notification.stories.svelte +228 -0
- package/dist/ui/components/{ToggleList.svelte.d.ts → notification/Notification.stories.svelte.d.ts} +9 -21
- package/dist/ui/components/notification/Notification.svelte +289 -0
- package/dist/ui/components/notification/Notification.svelte.d.ts +67 -0
- package/dist/ui/components/notification/index.d.ts +2 -0
- package/dist/ui/components/notification/index.js +1 -0
- package/dist/ui/components/notification/types.d.ts +68 -0
- package/dist/ui/components/notification/types.js +1 -0
- package/dist/ui/components/section/Section.stories.svelte +263 -0
- package/dist/ui/components/section/Section.stories.svelte.d.ts +27 -0
- package/dist/ui/components/section/Section.svelte +324 -0
- package/dist/ui/components/section/Section.svelte.d.ts +5 -0
- package/dist/ui/components/section/index.d.ts +2 -0
- package/dist/ui/components/section/index.js +1 -0
- package/dist/ui/components/section/types.d.ts +106 -0
- package/dist/ui/components/section/types.js +1 -0
- package/dist/ui/components/{ImageUpload.svelte → shared/ImageUpload.svelte} +3 -3
- package/dist/ui/components/{SelectBodyOrDivBlock.svelte → shared/SelectBodyOrDivBlock.svelte} +1 -1
- package/dist/ui/components/shared/index.d.ts +2 -0
- package/dist/ui/components/shared/index.js +2 -0
- package/dist/ui/index.css +33 -5
- package/dist/utils/api/checkIfAppModeIsDesign.d.ts +1 -2
- package/dist/utils/api/checkIfAppModeIsDesign.js +1 -2
- package/dist/utils/api/clipboard/handlePaste.d.ts +6 -37
- package/dist/utils/api/clipboard/handlePaste.js +2 -6
- package/dist/utils/api/getAllAssets.d.ts +1 -2
- package/dist/utils/api/getAllAssets.js +1 -2
- package/dist/utils/api/getFinsweetComponentsEnvironment.d.ts +1 -2
- package/dist/utils/api/getFinsweetComponentsEnvironment.js +3 -6
- package/dist/utils/api/index.d.ts +0 -1
- package/dist/utils/api/index.js +0 -1
- package/dist/utils/api/insertWithXSCP.d.ts +1 -2
- package/dist/utils/api/insertWithXSCP.js +1 -2
- package/dist/utils/auth/crossWindowLogin.d.ts +3 -0
- package/dist/utils/auth/crossWindowLogin.js +3 -0
- package/dist/utils/auth/index.d.ts +9 -25
- package/dist/utils/auth/index.js +9 -25
- package/dist/utils/browser-storage/localStorage.d.ts +4 -12
- package/dist/utils/browser-storage/localStorage.js +4 -12
- package/dist/utils/browser-storage/sessionStorage.d.ts +4 -12
- package/dist/utils/browser-storage/sessionStorage.js +4 -12
- package/dist/utils/custom-code/api.d.ts +3 -7
- package/dist/utils/custom-code/api.js +3 -7
- package/dist/utils/helpers/cleanupTooltipMessage.d.ts +1 -2
- package/dist/utils/helpers/cleanupTooltipMessage.js +1 -2
- package/dist/utils/helpers/goto.d.ts +1 -4
- package/dist/utils/helpers/goto.js +2 -7
- package/dist/utils/helpers/index.d.ts +1 -0
- package/dist/utils/helpers/index.js +1 -0
- package/dist/utils/helpers/noop.d.ts +1 -1
- package/dist/utils/helpers/noop.js +1 -1
- package/dist/utils/helpers/numbers.d.ts +4 -14
- package/dist/utils/helpers/numbers.js +4 -14
- package/dist/utils/helpers/objectsToModuleExports.d.ts +1 -3
- package/dist/utils/helpers/objectsToModuleExports.js +1 -3
- package/dist/utils/helpers/trimText.d.ts +1 -8
- package/dist/utils/helpers/trimText.js +1 -8
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/logger/index.d.ts +0 -2
- package/dist/utils/logger/index.js +0 -2
- package/dist/utils/webflow-canvas/attributes/getAllWebflowElementAttributes.d.ts +1 -3
- package/dist/utils/webflow-canvas/attributes/getAllWebflowElementAttributes.js +1 -3
- package/dist/utils/webflow-canvas/attributes/getInstanceNamesFromObject.d.ts +1 -5
- package/dist/utils/webflow-canvas/attributes/getInstanceNamesFromObject.js +1 -5
- package/dist/utils/webflow-canvas/attributes/getWebflowElementAttribute.d.ts +1 -4
- package/dist/utils/webflow-canvas/attributes/getWebflowElementAttribute.js +1 -4
- package/dist/utils/webflow-canvas/attributes/getWebflowElementTextContent.d.ts +1 -3
- package/dist/utils/webflow-canvas/attributes/getWebflowElementTextContent.js +1 -3
- package/dist/utils/webflow-canvas/attributes/removeWebflowElementAttribute.d.ts +1 -4
- package/dist/utils/webflow-canvas/attributes/removeWebflowElementAttribute.js +1 -4
- package/dist/utils/webflow-canvas/attributes/setStyles.d.ts +1 -3
- package/dist/utils/webflow-canvas/attributes/setStyles.js +1 -3
- package/dist/utils/webflow-canvas/attributes/setWebflowElementAttribute.d.ts +1 -8
- package/dist/utils/webflow-canvas/attributes/setWebflowElementAttribute.js +1 -13
- package/dist/utils/webflow-canvas/findInstanceElement.d.ts +0 -6
- package/dist/utils/webflow-canvas/findInstanceElement.js +1 -7
- package/dist/utils/webflow-canvas/getAllPages.d.ts +3 -10
- package/dist/utils/webflow-canvas/getAllPages.js +3 -10
- package/dist/utils/webflow-canvas/getSiteStagingUrl.d.ts +1 -4
- package/dist/utils/webflow-canvas/getSiteStagingUrl.js +1 -4
- package/dist/utils/webflow-canvas/index.d.ts +1 -0
- package/dist/utils/webflow-canvas/index.js +1 -0
- package/package.json +9 -2
- package/dist/stores/globalStore.d.ts +0 -10
- package/dist/stores/globalStore.js +0 -10
- package/dist/ui/components/ButtonGroup.svelte.d.ts +0 -28
- package/dist/ui/components/Checkbox.svelte +0 -94
- package/dist/ui/components/Checkbox.svelte.d.ts +0 -36
- package/dist/ui/components/Copy.svelte +0 -329
- package/dist/ui/components/Copy.svelte.d.ts +0 -35
- package/dist/ui/components/CustomModal.svelte +0 -192
- package/dist/ui/components/CustomModal.svelte.d.ts +0 -45
- package/dist/ui/components/DisableInEditMode.svelte +0 -66
- package/dist/ui/components/DisableInEditMode.svelte.d.ts +0 -33
- package/dist/ui/components/Divider.svelte +0 -31
- package/dist/ui/components/Divider.svelte.d.ts +0 -31
- package/dist/ui/components/Header.svelte +0 -30
- package/dist/ui/components/Header.svelte.d.ts +0 -20
- package/dist/ui/components/Iframe.svelte +0 -89
- package/dist/ui/components/Iframe.svelte.d.ts +0 -40
- package/dist/ui/components/InjectComponent.svelte +0 -297
- package/dist/ui/components/InjectComponent.svelte.d.ts +0 -27
- package/dist/ui/components/Modal.svelte +0 -139
- package/dist/ui/components/Modal.svelte.d.ts +0 -42
- package/dist/ui/components/Navbar.svelte +0 -132
- package/dist/ui/components/Navbar.svelte.d.ts +0 -29
- package/dist/ui/components/NoSettingsNeeded.svelte +0 -31
- package/dist/ui/components/Notification.svelte +0 -193
- package/dist/ui/components/Notification.svelte.d.ts +0 -64
- package/dist/ui/components/PlusMinusButton.svelte +0 -91
- package/dist/ui/components/PlusMinusButton.svelte.d.ts +0 -22
- package/dist/ui/components/PreviewBar.svelte +0 -40
- package/dist/ui/components/PreviewBar.svelte.d.ts +0 -20
- package/dist/ui/components/ScrollableContent.svelte +0 -18
- package/dist/ui/components/ScrollableContent.svelte.d.ts +0 -31
- package/dist/ui/components/Section.svelte +0 -97
- package/dist/ui/components/Section.svelte.d.ts +0 -50
- package/dist/ui/components/Spacer.svelte +0 -9
- package/dist/ui/components/Spacer.svelte.d.ts +0 -22
- package/dist/ui/components/SpinnerPlusMinus.svelte +0 -75
- package/dist/ui/components/SpinnerPlusMinus.svelte.d.ts +0 -23
- package/dist/ui/components/SpinnerUpDown.svelte +0 -194
- package/dist/ui/components/SpinnerUpDown.svelte.d.ts +0 -31
- package/dist/ui/components/Tabs.svelte +0 -71
- package/dist/ui/components/Tabs.svelte.d.ts +0 -26
- package/dist/ui/components/ToggleItem.svelte +0 -29
- package/dist/ui/components/ToggleList.svelte +0 -57
- package/dist/ui/components/buttons/FooterButton.svelte.d.ts +0 -10
- package/dist/ui/components/buttons/index.d.ts +0 -5
- package/dist/ui/components/buttons/index.js +0 -5
- package/dist/ui/components/clickable/Clickable.stories.svelte +0 -213
- package/dist/ui/components/clickable/Clickable.svelte +0 -93
- package/dist/ui/components/clickable/Clickable.svelte.d.ts +0 -4
- package/dist/ui/components/clickable/index.d.ts +0 -2
- package/dist/ui/components/clickable/index.js +0 -1
- package/dist/ui/components/clickable/types.d.ts +0 -17
- package/dist/utils/api/copyPaste/index.d.ts +0 -18
- /package/dist/ui/components/{buttons → button-group}/types.js +0 -0
- /package/dist/ui/components/{clickable → checkbox}/types.js +0 -0
- /package/dist/{utils/api/copyPaste/index.js → ui/components/controlled-buttons/types.js} +0 -0
- /package/dist/ui/components/layout/{ExampleLayout.svelte.d.ts → examples/ExampleLayout.svelte.d.ts} +0 -0
- /package/dist/ui/components/{ImageUpload.svelte.d.ts → shared/ImageUpload.svelte.d.ts} +0 -0
- /package/dist/ui/components/{SelectBodyOrDivBlock.svelte.d.ts → shared/SelectBodyOrDivBlock.svelte.d.ts} +0 -0
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
import Checkbox from './Checkbox.svelte';
|
|
2
|
+
const meta = {
|
|
3
|
+
title: 'Ui/Checkbox',
|
|
4
|
+
component: Checkbox,
|
|
5
|
+
parameters: {
|
|
6
|
+
layout: 'centered',
|
|
7
|
+
docs: {
|
|
8
|
+
description: {
|
|
9
|
+
component: 'A versatile checkbox component following MUI patterns with support for controlled/uncontrolled usage, checkbox and radio variants, and disabled states.'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
argTypes: {
|
|
15
|
+
checked: {
|
|
16
|
+
control: 'boolean',
|
|
17
|
+
description: 'If true, the component is checked. Use for controlled components.'
|
|
18
|
+
},
|
|
19
|
+
defaultChecked: {
|
|
20
|
+
control: 'boolean',
|
|
21
|
+
description: 'The default checked state. Use when the component is not controlled.'
|
|
22
|
+
},
|
|
23
|
+
disabled: {
|
|
24
|
+
control: 'boolean',
|
|
25
|
+
description: 'If true, the component is disabled.'
|
|
26
|
+
},
|
|
27
|
+
variant: {
|
|
28
|
+
control: { type: 'select' },
|
|
29
|
+
options: ['checkbox', 'radio'],
|
|
30
|
+
description: 'The checkbox type variant'
|
|
31
|
+
},
|
|
32
|
+
onChange: {
|
|
33
|
+
action: 'onChange',
|
|
34
|
+
description: 'Callback fired when the state is changed.'
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
export default meta;
|
|
39
|
+
// Basic stories
|
|
40
|
+
export const Default = {
|
|
41
|
+
args: {}
|
|
42
|
+
};
|
|
43
|
+
export const DefaultChecked = {
|
|
44
|
+
args: {
|
|
45
|
+
defaultChecked: true
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
export const Controlled = {
|
|
49
|
+
args: {
|
|
50
|
+
checked: true
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
// Variants
|
|
54
|
+
export const CheckboxVariant = {
|
|
55
|
+
args: {
|
|
56
|
+
variant: 'checkbox',
|
|
57
|
+
defaultChecked: true
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
export const RadioVariant = {
|
|
61
|
+
args: {
|
|
62
|
+
variant: 'radio',
|
|
63
|
+
defaultChecked: true
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
// States
|
|
67
|
+
export const Disabled = {
|
|
68
|
+
args: {
|
|
69
|
+
disabled: true
|
|
70
|
+
}
|
|
71
|
+
};
|
|
72
|
+
export const DisabledChecked = {
|
|
73
|
+
args: {
|
|
74
|
+
disabled: true,
|
|
75
|
+
defaultChecked: true
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
export const DisabledRadio = {
|
|
79
|
+
args: {
|
|
80
|
+
disabled: true,
|
|
81
|
+
defaultChecked: true,
|
|
82
|
+
variant: 'radio'
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
// Uncontrolled usage (default behavior)
|
|
86
|
+
export const Uncontrolled = {
|
|
87
|
+
args: {
|
|
88
|
+
defaultChecked: false
|
|
89
|
+
},
|
|
90
|
+
parameters: {
|
|
91
|
+
docs: {
|
|
92
|
+
description: {
|
|
93
|
+
story: 'Uncontrolled component manages its own state. Use defaultChecked to set initial state and onChange to listen for changes.'
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
// Interactive examples
|
|
99
|
+
export const Interactive = {
|
|
100
|
+
args: {
|
|
101
|
+
onChange: (checked) => {
|
|
102
|
+
console.log('Checkbox checked:', checked);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
};
|
|
106
|
+
export const InteractiveRadio = {
|
|
107
|
+
args: {
|
|
108
|
+
variant: 'radio',
|
|
109
|
+
onChange: (checked) => {
|
|
110
|
+
console.log('Radio checked:', checked);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
// Accessibility testing
|
|
115
|
+
export const AccessibilityTest = {
|
|
116
|
+
args: {
|
|
117
|
+
defaultChecked: false,
|
|
118
|
+
'aria-label': 'Accept terms and conditions'
|
|
119
|
+
},
|
|
120
|
+
parameters: {
|
|
121
|
+
docs: {
|
|
122
|
+
description: {
|
|
123
|
+
story: 'This story demonstrates proper ARIA attributes for screen readers. The checkbox can be operated with keyboard (Space or Enter keys).'
|
|
124
|
+
}
|
|
125
|
+
},
|
|
126
|
+
a11y: {
|
|
127
|
+
config: {
|
|
128
|
+
rules: [
|
|
129
|
+
{ id: 'button-name', enabled: true },
|
|
130
|
+
{ id: 'aria-allowed-attr', enabled: true }
|
|
131
|
+
]
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
// Multiple checkboxes showcase
|
|
137
|
+
export const MultipleCheckboxes = {
|
|
138
|
+
render: () => ({
|
|
139
|
+
Component: Checkbox,
|
|
140
|
+
props: {}
|
|
141
|
+
}),
|
|
142
|
+
parameters: {
|
|
143
|
+
docs: {
|
|
144
|
+
description: {
|
|
145
|
+
story: 'Example showing multiple checkboxes in different states.'
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
// Focus demonstration
|
|
151
|
+
export const FocusStates = {
|
|
152
|
+
args: {
|
|
153
|
+
defaultChecked: false
|
|
154
|
+
},
|
|
155
|
+
parameters: {
|
|
156
|
+
docs: {
|
|
157
|
+
description: {
|
|
158
|
+
story: 'Click on the checkbox and use Tab to see focus indicators. The component supports keyboard navigation with Space and Enter keys.'
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import { SquareCheckIcon } from '../../icons';
|
|
3
|
+
import type { CheckboxProps } from './types.js';
|
|
4
|
+
|
|
5
|
+
let {
|
|
6
|
+
checked,
|
|
7
|
+
defaultChecked = false,
|
|
8
|
+
disabled = false,
|
|
9
|
+
variant = 'checkbox',
|
|
10
|
+
onChange,
|
|
11
|
+
class: className = '',
|
|
12
|
+
...restProps
|
|
13
|
+
}: CheckboxProps = $props();
|
|
14
|
+
|
|
15
|
+
// Component state using Svelte 5 runes
|
|
16
|
+
let checkboxElement: HTMLDivElement | undefined = $state();
|
|
17
|
+
|
|
18
|
+
// Internal state for uncontrolled usage
|
|
19
|
+
let internalChecked = $state(defaultChecked);
|
|
20
|
+
|
|
21
|
+
// Determine if component is controlled (checked prop is provided)
|
|
22
|
+
let isControlled = $derived(checked !== undefined);
|
|
23
|
+
|
|
24
|
+
// Current checked state - use controlled value if provided, otherwise internal state
|
|
25
|
+
let isChecked = $derived(isControlled ? checked : internalChecked);
|
|
26
|
+
let isDisabled = $derived(disabled);
|
|
27
|
+
|
|
28
|
+
// CSS class computation
|
|
29
|
+
let checkboxClasses = $derived(
|
|
30
|
+
`
|
|
31
|
+
checkbox
|
|
32
|
+
checkbox--${variant}
|
|
33
|
+
${isChecked ? 'checkbox--checked' : ''}
|
|
34
|
+
${isDisabled ? 'checkbox--disabled' : ''}
|
|
35
|
+
${className}
|
|
36
|
+
`
|
|
37
|
+
.trim()
|
|
38
|
+
.replace(/\s+/g, ' ')
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Handles click events on the checkbox
|
|
43
|
+
*/
|
|
44
|
+
const handleClick = (): void => {
|
|
45
|
+
if (isDisabled) return;
|
|
46
|
+
|
|
47
|
+
const newChecked = !isChecked;
|
|
48
|
+
|
|
49
|
+
// Update internal state if uncontrolled
|
|
50
|
+
if (!isControlled) {
|
|
51
|
+
internalChecked = newChecked;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Always call onChange callback
|
|
55
|
+
onChange?.(newChecked);
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Handles keyboard events for accessibility
|
|
60
|
+
*/
|
|
61
|
+
const handleKeydown = (event: KeyboardEvent): void => {
|
|
62
|
+
if (isDisabled) return;
|
|
63
|
+
|
|
64
|
+
if (event.key === ' ' || event.key === 'Enter') {
|
|
65
|
+
event.preventDefault();
|
|
66
|
+
handleClick();
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
</script>
|
|
70
|
+
|
|
71
|
+
<div
|
|
72
|
+
bind:this={checkboxElement}
|
|
73
|
+
class={checkboxClasses}
|
|
74
|
+
onclick={handleClick}
|
|
75
|
+
onkeydown={handleKeydown}
|
|
76
|
+
role="checkbox"
|
|
77
|
+
tabindex={isDisabled ? -1 : 0}
|
|
78
|
+
aria-checked={isChecked}
|
|
79
|
+
aria-disabled={isDisabled}
|
|
80
|
+
{...restProps}
|
|
81
|
+
>
|
|
82
|
+
{#if isChecked}
|
|
83
|
+
<SquareCheckIcon />
|
|
84
|
+
{/if}
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<style>
|
|
88
|
+
.checkbox {
|
|
89
|
+
width: 16px;
|
|
90
|
+
height: 16px;
|
|
91
|
+
border-radius: 4px;
|
|
92
|
+
border: 2px solid #ffffff1a;
|
|
93
|
+
display: flex;
|
|
94
|
+
justify-content: center;
|
|
95
|
+
align-items: center;
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
transition: all 0.2s ease-in-out;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.checkbox--radio {
|
|
101
|
+
border-radius: 50%;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.checkbox :global(svg) {
|
|
105
|
+
width: 16px;
|
|
106
|
+
height: 16px;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.checkbox--checked {
|
|
110
|
+
color: white;
|
|
111
|
+
border: none;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
.checkbox--checked :global(svg) {
|
|
115
|
+
color: white;
|
|
116
|
+
background: #006acc;
|
|
117
|
+
border-radius: 4px;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
.checkbox--checked.checkbox--radio :global(svg) {
|
|
121
|
+
border-radius: 50%;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
.checkbox--disabled {
|
|
125
|
+
cursor: not-allowed;
|
|
126
|
+
opacity: 0.6;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
.checkbox:focus-visible {
|
|
130
|
+
outline: 2px solid var(--color-focus, #006acc);
|
|
131
|
+
outline-offset: 2px;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
.checkbox:hover:not(.checkbox--disabled) {
|
|
135
|
+
border-color: #ffffff33;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.checkbox--checked:hover:not(.checkbox--disabled) :global(svg) {
|
|
139
|
+
background: #0056a3;
|
|
140
|
+
}
|
|
141
|
+
</style>
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as Checkbox } from './Checkbox.svelte';
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { HTMLAttributes } from 'svelte/elements';
|
|
2
|
+
export type CheckboxVariant = 'checkbox' | 'radio';
|
|
3
|
+
export interface CheckboxProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onclick' | 'onchange'> {
|
|
4
|
+
/**
|
|
5
|
+
* If true, the component is checked.
|
|
6
|
+
*/
|
|
7
|
+
checked?: boolean;
|
|
8
|
+
/**
|
|
9
|
+
* The default checked state. Use when the component is not controlled.
|
|
10
|
+
*/
|
|
11
|
+
defaultChecked?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* If true, the component is disabled.
|
|
14
|
+
*/
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* The checkbox type variant
|
|
18
|
+
*/
|
|
19
|
+
variant?: CheckboxVariant;
|
|
20
|
+
/**
|
|
21
|
+
* Callback fired when the state is changed.
|
|
22
|
+
* @param checked - The new checked state
|
|
23
|
+
*/
|
|
24
|
+
onChange?: (checked: boolean) => void;
|
|
25
|
+
/**
|
|
26
|
+
* Additional CSS classes
|
|
27
|
+
*/
|
|
28
|
+
class?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface CheckboxChangeEvent {
|
|
31
|
+
checked: boolean;
|
|
32
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import type { StoryObj } from '@storybook/sveltekit';
|
|
2
|
+
import type { ControlledButtonsProps } from './types.js';
|
|
3
|
+
declare const meta: {
|
|
4
|
+
title: string;
|
|
5
|
+
component: import("svelte").Component<ControlledButtonsProps, {}, "">;
|
|
6
|
+
parameters: {
|
|
7
|
+
layout: string;
|
|
8
|
+
docs: {
|
|
9
|
+
description: {
|
|
10
|
+
component: string;
|
|
11
|
+
};
|
|
12
|
+
};
|
|
13
|
+
};
|
|
14
|
+
tags: string[];
|
|
15
|
+
argTypes: {
|
|
16
|
+
buttons: {
|
|
17
|
+
control: "object";
|
|
18
|
+
description: string;
|
|
19
|
+
};
|
|
20
|
+
class: {
|
|
21
|
+
control: "text";
|
|
22
|
+
description: string;
|
|
23
|
+
};
|
|
24
|
+
};
|
|
25
|
+
};
|
|
26
|
+
export default meta;
|
|
27
|
+
type Story = StoryObj<typeof meta>;
|
|
28
|
+
export declare const Primary: Story;
|
|
29
|
+
export declare const WithLoading: Story;
|
|
30
|
+
export declare const WithTooltip: Story;
|
|
31
|
+
export declare const WithPopup: Story;
|
|
32
|
+
export declare const Mixed: Story;
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
import ControlledButtons from './ControlledButtons.svelte';
|
|
2
|
+
const meta = {
|
|
3
|
+
title: 'UI/ControlledButtons',
|
|
4
|
+
component: ControlledButtons,
|
|
5
|
+
parameters: {
|
|
6
|
+
layout: 'centered',
|
|
7
|
+
docs: {
|
|
8
|
+
description: {
|
|
9
|
+
component: 'A controlled buttons component that renders multiple buttons with various configurations including tooltips, popups, and different variants.'
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
},
|
|
13
|
+
tags: ['autodocs'],
|
|
14
|
+
argTypes: {
|
|
15
|
+
buttons: {
|
|
16
|
+
control: 'object',
|
|
17
|
+
description: 'Array of button configurations to render'
|
|
18
|
+
},
|
|
19
|
+
class: {
|
|
20
|
+
control: 'text',
|
|
21
|
+
description: 'Additional CSS classes to apply to the component'
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
export default meta;
|
|
26
|
+
// Basic buttons
|
|
27
|
+
export const Primary = {
|
|
28
|
+
args: {
|
|
29
|
+
buttons: [
|
|
30
|
+
{
|
|
31
|
+
id: 'save',
|
|
32
|
+
text: 'Save',
|
|
33
|
+
variant: 'primary',
|
|
34
|
+
onClick: () => console.log('Save clicked')
|
|
35
|
+
},
|
|
36
|
+
{
|
|
37
|
+
id: 'cancel',
|
|
38
|
+
text: 'Cancel',
|
|
39
|
+
variant: 'secondary',
|
|
40
|
+
onClick: () => console.log('Cancel clicked')
|
|
41
|
+
}
|
|
42
|
+
]
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
// Buttons with loading states
|
|
46
|
+
export const WithLoading = {
|
|
47
|
+
args: {
|
|
48
|
+
buttons: [
|
|
49
|
+
{
|
|
50
|
+
id: 'save',
|
|
51
|
+
text: 'Saving...',
|
|
52
|
+
variant: 'primary',
|
|
53
|
+
loading: true,
|
|
54
|
+
onClick: () => console.log('Save clicked')
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
id: 'cancel',
|
|
58
|
+
text: 'Cancel',
|
|
59
|
+
variant: 'secondary',
|
|
60
|
+
disabled: true,
|
|
61
|
+
onClick: () => console.log('Cancel clicked')
|
|
62
|
+
}
|
|
63
|
+
]
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
// Button with tooltip
|
|
67
|
+
export const WithTooltip = {
|
|
68
|
+
args: {
|
|
69
|
+
buttons: [
|
|
70
|
+
{
|
|
71
|
+
id: 'save',
|
|
72
|
+
text: 'Save',
|
|
73
|
+
variant: 'primary',
|
|
74
|
+
onClick: () => console.log('Save clicked'),
|
|
75
|
+
tooltip: {
|
|
76
|
+
content: 'Save your changes to the project',
|
|
77
|
+
placement: 'top',
|
|
78
|
+
showArrow: true
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
]
|
|
82
|
+
}
|
|
83
|
+
};
|
|
84
|
+
// Button with popup menu
|
|
85
|
+
export const WithPopup = {
|
|
86
|
+
args: {
|
|
87
|
+
buttons: [
|
|
88
|
+
{
|
|
89
|
+
id: 'actions',
|
|
90
|
+
text: 'Actions',
|
|
91
|
+
variant: 'primary',
|
|
92
|
+
popupButtons: [
|
|
93
|
+
{
|
|
94
|
+
text: 'Edit',
|
|
95
|
+
description: 'Edit the current item',
|
|
96
|
+
onClick: () => console.log('Edit clicked')
|
|
97
|
+
},
|
|
98
|
+
{
|
|
99
|
+
text: 'Delete',
|
|
100
|
+
description: 'Remove the current item',
|
|
101
|
+
onClick: () => console.log('Delete clicked')
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
text: 'Duplicate',
|
|
105
|
+
description: 'Create a copy of the item',
|
|
106
|
+
onClick: () => console.log('Duplicate clicked')
|
|
107
|
+
}
|
|
108
|
+
]
|
|
109
|
+
}
|
|
110
|
+
]
|
|
111
|
+
}
|
|
112
|
+
};
|
|
113
|
+
// Mixed button types
|
|
114
|
+
export const Mixed = {
|
|
115
|
+
args: {
|
|
116
|
+
buttons: [
|
|
117
|
+
{
|
|
118
|
+
id: 'save',
|
|
119
|
+
text: 'Save',
|
|
120
|
+
variant: 'primary',
|
|
121
|
+
onClick: () => console.log('Save clicked'),
|
|
122
|
+
tooltip: {
|
|
123
|
+
content: 'Save your changes',
|
|
124
|
+
placement: 'top'
|
|
125
|
+
}
|
|
126
|
+
},
|
|
127
|
+
{
|
|
128
|
+
id: 'actions',
|
|
129
|
+
text: 'More Actions',
|
|
130
|
+
variant: 'secondary',
|
|
131
|
+
popupButtons: [
|
|
132
|
+
{
|
|
133
|
+
text: 'Export',
|
|
134
|
+
description: 'Export data to file',
|
|
135
|
+
onClick: () => console.log('Export clicked')
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
text: 'Import',
|
|
139
|
+
description: 'Import data from file',
|
|
140
|
+
onClick: () => console.log('Import clicked')
|
|
141
|
+
}
|
|
142
|
+
]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
id: 'cancel',
|
|
146
|
+
text: 'Cancel',
|
|
147
|
+
variant: 'secondary',
|
|
148
|
+
onClick: () => console.log('Cancel clicked')
|
|
149
|
+
}
|
|
150
|
+
]
|
|
151
|
+
}
|
|
152
|
+
};
|
|
@@ -1,70 +1,17 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
import { createFormSubscription, globalStore } from '../../../stores';
|
|
5
|
-
import { canAccessFeature, finsweetUser } from '../../../utils';
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
6
3
|
|
|
7
4
|
import { ChevronIcon } from '../../icons';
|
|
8
5
|
import { Button, Text, Tooltip } from '..';
|
|
9
|
-
import Section from '../
|
|
10
|
-
import type {
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Accept individual buttons
|
|
14
|
-
*/
|
|
15
|
-
let {
|
|
16
|
-
editMode = false,
|
|
17
|
-
formKey,
|
|
18
|
-
buttons
|
|
19
|
-
}: {
|
|
20
|
-
buttons: ButtonItem[];
|
|
21
|
-
editMode: boolean;
|
|
22
|
-
formKey: string;
|
|
23
|
-
} = $props();
|
|
24
|
-
|
|
25
|
-
// Create reactive state for selected element
|
|
26
|
-
let selectedElement = $state<AnyElement | null>(null);
|
|
27
|
-
|
|
28
|
-
/**
|
|
29
|
-
* Check if user is logged in
|
|
30
|
-
*/
|
|
31
|
-
const isLoggedIn = $derived(!!$finsweetUser?.user?.userId);
|
|
32
|
-
const form = createFormSubscription(formKey);
|
|
33
|
-
|
|
34
|
-
const unsubscribe =
|
|
35
|
-
typeof webflow !== 'undefined'
|
|
36
|
-
? webflow?.subscribe?.('selectedelement', (el) => {
|
|
37
|
-
selectedElement = el;
|
|
38
|
-
})
|
|
39
|
-
: () => {};
|
|
40
|
-
|
|
41
|
-
onDestroy(() => unsubscribe());
|
|
42
|
-
|
|
43
|
-
const buttonItems = $derived(() => {
|
|
44
|
-
const isEditting = editMode || !!$globalStore?.editMode;
|
|
45
|
-
const needsRepair = $globalStore?.repairMode && isEditting;
|
|
6
|
+
import { Section } from '../section';
|
|
7
|
+
import type { ControlledButtonItem, ControlledButtonsProps } from './types';
|
|
46
8
|
|
|
47
|
-
|
|
48
|
-
'canManageLibrary'
|
|
49
|
-
]);
|
|
50
|
-
|
|
51
|
-
return buttons.filter((item: ButtonItem) => {
|
|
52
|
-
// validation is handled in parent component
|
|
53
|
-
if (item.escapeValidation) return true;
|
|
54
|
-
|
|
55
|
-
//if not logged in remove library
|
|
56
|
-
if (!hasAccess?.granted) return item.type !== 'library';
|
|
57
|
-
|
|
58
|
-
// Filter out library buttons in create mode
|
|
59
|
-
if (isEditting && !needsRepair) return true;
|
|
60
|
-
return item.id !== 'save' && item.type !== 'library';
|
|
61
|
-
});
|
|
62
|
-
});
|
|
9
|
+
let { buttons, class: className = '' }: ControlledButtonsProps = $props();
|
|
63
10
|
</script>
|
|
64
11
|
|
|
65
|
-
<div class="footer">
|
|
66
|
-
<div class="
|
|
67
|
-
{#each
|
|
12
|
+
<div class="footer {className}">
|
|
13
|
+
<div class="controlled-buttons">
|
|
14
|
+
{#each buttons as button, index (button.id || index)}
|
|
68
15
|
{#if button.show !== false}
|
|
69
16
|
<!-- Button with popup menu -->
|
|
70
17
|
{#if button?.popupButtons?.length}
|
|
@@ -72,6 +19,7 @@
|
|
|
72
19
|
position="fixed"
|
|
73
20
|
placement="top-start"
|
|
74
21
|
offsetVal={8}
|
|
22
|
+
padding="0"
|
|
75
23
|
showArrow={false}
|
|
76
24
|
listener={button.popupTrigger || 'click'}
|
|
77
25
|
listenerout={button.popupTrigger || 'click'}
|
|
@@ -93,10 +41,10 @@
|
|
|
93
41
|
{#each button.popupButtons || [] as popupButton, popupIndex (popupIndex)}
|
|
94
42
|
{#if popupButton.show !== false}
|
|
95
43
|
<Section
|
|
96
|
-
|
|
44
|
+
class="link"
|
|
97
45
|
clickable
|
|
98
46
|
disabled={popupButton.disabled || popupButton.loading}
|
|
99
|
-
|
|
47
|
+
onclick={(e: MouseEvent) => {
|
|
100
48
|
e.stopPropagation();
|
|
101
49
|
e.preventDefault();
|
|
102
50
|
if (popupButton.disabled || popupButton.loading) return;
|
|
@@ -132,6 +80,7 @@
|
|
|
132
80
|
<!-- Button with tooltip -->
|
|
133
81
|
{:else if button.tooltip}
|
|
134
82
|
<Tooltip
|
|
83
|
+
padding="0"
|
|
135
84
|
width={button.tooltip?.width || '160px'}
|
|
136
85
|
placement={button.tooltip?.placement || 'top'}
|
|
137
86
|
offsetVal={10}
|
|
@@ -180,10 +129,10 @@
|
|
|
180
129
|
.footer :global(.w-button svg) {
|
|
181
130
|
transform: rotate(270deg);
|
|
182
131
|
}
|
|
183
|
-
.
|
|
132
|
+
.controlled-buttons :global(.target:not(:has(.dropdown-label))) {
|
|
184
133
|
width: max-content !important;
|
|
185
134
|
}
|
|
186
|
-
.
|
|
135
|
+
.controlled-buttons :global(.target .tooltip) {
|
|
187
136
|
padding: 8px 0;
|
|
188
137
|
gap: 0;
|
|
189
138
|
}
|
|
@@ -191,9 +140,12 @@
|
|
|
191
140
|
color: var(--yellowText);
|
|
192
141
|
}
|
|
193
142
|
.footer :global(.tooltip) {
|
|
194
|
-
padding: 0;
|
|
195
143
|
width: 100%;
|
|
196
144
|
}
|
|
145
|
+
.footer :global(.tooltip .content-wrapper) {
|
|
146
|
+
width: 100%;
|
|
147
|
+
}
|
|
148
|
+
|
|
197
149
|
.footer :global(.tooltip) {
|
|
198
150
|
padding: 0 !important;
|
|
199
151
|
flex-direction: column;
|
|
@@ -211,7 +163,7 @@
|
|
|
211
163
|
.tooltip-content.invalid-selection :global(svg) {
|
|
212
164
|
color: var(--yellowText);
|
|
213
165
|
}
|
|
214
|
-
.
|
|
166
|
+
.controlled-buttons {
|
|
215
167
|
display: flex;
|
|
216
168
|
flex-direction: row;
|
|
217
169
|
align-items: center;
|
|
@@ -236,7 +188,6 @@
|
|
|
236
188
|
min-width: 150px;
|
|
237
189
|
background: var(--background);
|
|
238
190
|
border-radius: 4px;
|
|
239
|
-
padding: 4px;
|
|
240
191
|
}
|
|
241
192
|
|
|
242
193
|
.popup-content-list {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as ControlledButtons } from './ControlledButtons.svelte';
|