@finsweet/webflow-apps-utils 1.0.1 → 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 +4 -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/icons/LineChartIcon.svelte +8 -0
- package/dist/ui/icons/LineChartIcon.svelte.d.ts +26 -0
- package/dist/ui/icons/index.d.ts +2 -1
- package/dist/ui/icons/index.js +2 -1
- 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
|
@@ -74,6 +74,22 @@ declare const meta: {
|
|
|
74
74
|
control: string;
|
|
75
75
|
description: string;
|
|
76
76
|
};
|
|
77
|
+
showSteppers: {
|
|
78
|
+
control: string;
|
|
79
|
+
description: string;
|
|
80
|
+
};
|
|
81
|
+
step: {
|
|
82
|
+
control: string;
|
|
83
|
+
description: string;
|
|
84
|
+
};
|
|
85
|
+
min: {
|
|
86
|
+
control: string;
|
|
87
|
+
description: string;
|
|
88
|
+
};
|
|
89
|
+
max: {
|
|
90
|
+
control: string;
|
|
91
|
+
description: string;
|
|
92
|
+
};
|
|
77
93
|
};
|
|
78
94
|
};
|
|
79
95
|
export default meta;
|
|
@@ -84,6 +100,14 @@ export declare const WithPlaceholder: Story;
|
|
|
84
100
|
export declare const EmailInput: Story;
|
|
85
101
|
export declare const PasswordInput: Story;
|
|
86
102
|
export declare const NumberInput: Story;
|
|
103
|
+
export declare const NumberWithSteppers: Story;
|
|
104
|
+
export declare const SteppersWithCustomStep: Story;
|
|
105
|
+
export declare const SteppersWithMinMax: Story;
|
|
106
|
+
export declare const SteppersWithDecimals: Story;
|
|
107
|
+
export declare const SteppersAtMinValue: Story;
|
|
108
|
+
export declare const SteppersAtMaxValue: Story;
|
|
109
|
+
export declare const SteppersDisabled: Story;
|
|
110
|
+
export declare const SteppersReadonly: Story;
|
|
87
111
|
export declare const Disabled: Story;
|
|
88
112
|
export declare const ReadOnly: Story;
|
|
89
113
|
export declare const Invalid: Story;
|
|
@@ -69,6 +69,22 @@ const meta = {
|
|
|
69
69
|
minLength: {
|
|
70
70
|
control: 'number',
|
|
71
71
|
description: 'Minimum input length'
|
|
72
|
+
},
|
|
73
|
+
showSteppers: {
|
|
74
|
+
control: 'boolean',
|
|
75
|
+
description: 'Shows increment/decrement buttons for number inputs (requires type="number")'
|
|
76
|
+
},
|
|
77
|
+
step: {
|
|
78
|
+
control: 'number',
|
|
79
|
+
description: 'Step value for increment/decrement (default: 1)'
|
|
80
|
+
},
|
|
81
|
+
min: {
|
|
82
|
+
control: 'number',
|
|
83
|
+
description: 'Minimum value for number input'
|
|
84
|
+
},
|
|
85
|
+
max: {
|
|
86
|
+
control: 'number',
|
|
87
|
+
description: 'Maximum value for number input'
|
|
72
88
|
}
|
|
73
89
|
}
|
|
74
90
|
};
|
|
@@ -109,6 +125,88 @@ export const NumberInput = {
|
|
|
109
125
|
placeholder: 'Enter a number...'
|
|
110
126
|
}
|
|
111
127
|
};
|
|
128
|
+
// Stepper functionality
|
|
129
|
+
export const NumberWithSteppers = {
|
|
130
|
+
args: {
|
|
131
|
+
type: 'number',
|
|
132
|
+
showSteppers: true,
|
|
133
|
+
value: '10',
|
|
134
|
+
placeholder: 'Enter a number...'
|
|
135
|
+
}
|
|
136
|
+
};
|
|
137
|
+
export const SteppersWithCustomStep = {
|
|
138
|
+
args: {
|
|
139
|
+
type: 'number',
|
|
140
|
+
showSteppers: true,
|
|
141
|
+
value: '5',
|
|
142
|
+
step: 5,
|
|
143
|
+
placeholder: 'Increments by 5...'
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
export const SteppersWithMinMax = {
|
|
147
|
+
args: {
|
|
148
|
+
type: 'number',
|
|
149
|
+
showSteppers: true,
|
|
150
|
+
value: '50',
|
|
151
|
+
min: 0,
|
|
152
|
+
max: 100,
|
|
153
|
+
step: 10,
|
|
154
|
+
placeholder: 'Range: 0-100, Step: 10'
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
export const SteppersWithDecimals = {
|
|
158
|
+
args: {
|
|
159
|
+
type: 'number',
|
|
160
|
+
showSteppers: true,
|
|
161
|
+
value: '1.5',
|
|
162
|
+
step: 0.5,
|
|
163
|
+
min: 0,
|
|
164
|
+
max: 10,
|
|
165
|
+
placeholder: 'Decimal steps...'
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
export const SteppersAtMinValue = {
|
|
169
|
+
args: {
|
|
170
|
+
type: 'number',
|
|
171
|
+
showSteppers: true,
|
|
172
|
+
value: '0',
|
|
173
|
+
min: 0,
|
|
174
|
+
max: 100,
|
|
175
|
+
step: 1,
|
|
176
|
+
placeholder: 'At minimum value'
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
export const SteppersAtMaxValue = {
|
|
180
|
+
args: {
|
|
181
|
+
type: 'number',
|
|
182
|
+
showSteppers: true,
|
|
183
|
+
value: '100',
|
|
184
|
+
min: 0,
|
|
185
|
+
max: 100,
|
|
186
|
+
step: 1,
|
|
187
|
+
placeholder: 'At maximum value'
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
export const SteppersDisabled = {
|
|
191
|
+
args: {
|
|
192
|
+
type: 'number',
|
|
193
|
+
showSteppers: true,
|
|
194
|
+
value: '25',
|
|
195
|
+
disabled: true,
|
|
196
|
+
step: 5,
|
|
197
|
+
placeholder: 'Disabled with steppers'
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
export const SteppersReadonly = {
|
|
201
|
+
args: {
|
|
202
|
+
type: 'number',
|
|
203
|
+
showSteppers: true,
|
|
204
|
+
value: '75',
|
|
205
|
+
readonly: true,
|
|
206
|
+
step: 5,
|
|
207
|
+
placeholder: 'Readonly with steppers'
|
|
208
|
+
}
|
|
209
|
+
};
|
|
112
210
|
// States
|
|
113
211
|
export const Disabled = {
|
|
114
212
|
args: {
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import { onMount } from 'svelte';
|
|
4
4
|
|
|
5
|
+
import { ChevronIcon } from '../../icons';
|
|
5
6
|
import { Text, Tooltip } from '..';
|
|
6
7
|
import type { InputProps } from './types.js';
|
|
7
8
|
|
|
@@ -23,33 +24,80 @@
|
|
|
23
24
|
type = 'text',
|
|
24
25
|
alert = null,
|
|
25
26
|
pill = null,
|
|
27
|
+
showSteppers = false,
|
|
28
|
+
step = 1,
|
|
29
|
+
min = undefined,
|
|
30
|
+
max = undefined,
|
|
26
31
|
oninput,
|
|
27
32
|
onblur,
|
|
28
33
|
onfocus,
|
|
29
34
|
onkeydown,
|
|
35
|
+
onValueChange,
|
|
30
36
|
class: className = '',
|
|
31
37
|
children,
|
|
32
38
|
...restProps
|
|
33
39
|
}: InputProps = $props();
|
|
34
40
|
|
|
41
|
+
// Validation: showSteppers can only be used with type="number"
|
|
42
|
+
if (showSteppers && type !== 'number') {
|
|
43
|
+
throw new Error('showSteppers can only be used when type="number"');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Validation: showSteppers and units cannot be used together
|
|
47
|
+
if (showSteppers && units) {
|
|
48
|
+
throw new Error('showSteppers and units cannot be used together');
|
|
49
|
+
}
|
|
50
|
+
|
|
35
51
|
// Component state using Svelte 5 runes
|
|
36
52
|
let inputElement: HTMLInputElement | undefined = $state();
|
|
37
53
|
let pillElement: HTMLSpanElement | undefined = $state();
|
|
38
54
|
let pillWidth = $state(0);
|
|
39
55
|
|
|
40
|
-
//
|
|
41
|
-
let
|
|
56
|
+
// Internal reactive state for input value that updates with steppers
|
|
57
|
+
let internalValue = $derived(value);
|
|
58
|
+
|
|
59
|
+
// Track HTML5 validation state
|
|
60
|
+
let isValidationInvalid = $state(false);
|
|
61
|
+
|
|
62
|
+
// Use internal value for reactive state management
|
|
63
|
+
let currInputValue = $derived(internalValue);
|
|
42
64
|
let computedColor = $derived(currInputValue ? 'var(--actionPrimaryText)' : 'var(--text3)');
|
|
43
65
|
|
|
44
66
|
let hasPill = $derived(currInputValue && pill);
|
|
45
67
|
let hasAlert = $derived(alert?.message);
|
|
46
68
|
|
|
69
|
+
// Parse numeric value for stepper operations
|
|
70
|
+
let numericValue = $derived.by(() => {
|
|
71
|
+
if (!showSteppers || !currInputValue) return 0;
|
|
72
|
+
const parsed = parseFloat(currInputValue);
|
|
73
|
+
return isNaN(parsed) ? 0 : parsed;
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Check if increment/decrement buttons should be disabled
|
|
77
|
+
let canIncrement = $derived.by(() => {
|
|
78
|
+
if (!showSteppers || disabled || readonly) return false;
|
|
79
|
+
if (max !== undefined) return numericValue < max;
|
|
80
|
+
return true;
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
let canDecrement = $derived.by(() => {
|
|
84
|
+
if (!showSteppers || disabled || readonly) return false;
|
|
85
|
+
if (min !== undefined) return numericValue > min;
|
|
86
|
+
return true;
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
// Sync external value prop changes to internal state
|
|
90
|
+
$effect(() => {
|
|
91
|
+
internalValue = value;
|
|
92
|
+
});
|
|
93
|
+
|
|
47
94
|
let wrapperClasses = $derived(
|
|
48
95
|
`
|
|
49
96
|
webflow-input-wrapper
|
|
50
97
|
${units ? 'units' : ''}
|
|
98
|
+
${showSteppers ? 'steppers' : ''}
|
|
51
99
|
${disabled ? 'disabled' : ''}
|
|
52
|
-
${invalid || hasAlert ? 'invalid' : ''}
|
|
100
|
+
${invalid || hasAlert || isValidationInvalid ? 'invalid' : ''}
|
|
53
101
|
${className}
|
|
54
102
|
`
|
|
55
103
|
.trim()
|
|
@@ -134,6 +182,51 @@
|
|
|
134
182
|
}
|
|
135
183
|
});
|
|
136
184
|
|
|
185
|
+
/**
|
|
186
|
+
* Updates validation state based on HTML5 input validity
|
|
187
|
+
*/
|
|
188
|
+
const updateValidationState = () => {
|
|
189
|
+
if (inputElement && type === 'number') {
|
|
190
|
+
// Check if the input has any validation errors
|
|
191
|
+
isValidationInvalid = !inputElement.validity.valid;
|
|
192
|
+
} else {
|
|
193
|
+
isValidationInvalid = false;
|
|
194
|
+
}
|
|
195
|
+
};
|
|
196
|
+
|
|
197
|
+
// Update validation state when input value changes
|
|
198
|
+
$effect(() => {
|
|
199
|
+
if (inputElement) {
|
|
200
|
+
// Use setTimeout to ensure the input element has been updated
|
|
201
|
+
setTimeout(updateValidationState, 0);
|
|
202
|
+
}
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
// Listen for form reset events to update internal state
|
|
206
|
+
$effect(() => {
|
|
207
|
+
if (inputElement) {
|
|
208
|
+
const form = inputElement.closest('form');
|
|
209
|
+
if (form) {
|
|
210
|
+
const handleFormReset = () => {
|
|
211
|
+
// Use setTimeout to allow the form reset to complete first
|
|
212
|
+
setTimeout(() => {
|
|
213
|
+
if (inputElement) {
|
|
214
|
+
const resetValue = inputElement.value;
|
|
215
|
+
internalValue = resetValue;
|
|
216
|
+
updateValidationState();
|
|
217
|
+
}
|
|
218
|
+
}, 0);
|
|
219
|
+
};
|
|
220
|
+
|
|
221
|
+
form.addEventListener('reset', handleFormReset);
|
|
222
|
+
|
|
223
|
+
return () => {
|
|
224
|
+
form.removeEventListener('reset', handleFormReset);
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
|
|
137
230
|
/**
|
|
138
231
|
* Handles input events
|
|
139
232
|
*/
|
|
@@ -141,10 +234,24 @@
|
|
|
141
234
|
const target = event.target as HTMLInputElement;
|
|
142
235
|
const inputValue = target?.value?.trim() || '';
|
|
143
236
|
|
|
237
|
+
// Update internal state for reactivity
|
|
238
|
+
internalValue = inputValue;
|
|
239
|
+
|
|
144
240
|
if (pill) {
|
|
145
241
|
setTimeout(updatePillPosition, 0);
|
|
146
242
|
}
|
|
147
243
|
|
|
244
|
+
// Call numeric value change handler for any number input when value is numeric
|
|
245
|
+
if (type === 'number' && inputValue) {
|
|
246
|
+
const parsed = parseFloat(inputValue);
|
|
247
|
+
if (!isNaN(parsed)) {
|
|
248
|
+
onValueChange?.(parsed);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
// Update validation state for real-time feedback
|
|
253
|
+
updateValidationState();
|
|
254
|
+
|
|
148
255
|
oninput?.(inputValue);
|
|
149
256
|
};
|
|
150
257
|
|
|
@@ -169,9 +276,78 @@
|
|
|
169
276
|
* Handles keydown events
|
|
170
277
|
*/
|
|
171
278
|
const handleKeydown = (event: KeyboardEvent) => {
|
|
279
|
+
// Handle arrow key increments/decrements when steppers are enabled
|
|
280
|
+
if (showSteppers && !disabled && !readonly) {
|
|
281
|
+
if (event.key === 'ArrowUp') {
|
|
282
|
+
event.preventDefault();
|
|
283
|
+
handleIncrement();
|
|
284
|
+
} else if (event.key === 'ArrowDown') {
|
|
285
|
+
event.preventDefault();
|
|
286
|
+
handleDecrement();
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
172
290
|
onkeydown?.(event);
|
|
173
291
|
};
|
|
174
292
|
|
|
293
|
+
/**
|
|
294
|
+
* Handles increment button click
|
|
295
|
+
*/
|
|
296
|
+
const handleIncrement = () => {
|
|
297
|
+
if (!canIncrement) return;
|
|
298
|
+
|
|
299
|
+
const currentNum = numericValue;
|
|
300
|
+
let newValue = currentNum + step;
|
|
301
|
+
|
|
302
|
+
// Apply max constraint
|
|
303
|
+
if (max !== undefined && newValue > max) {
|
|
304
|
+
newValue = max;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
const newStringValue = newValue.toString();
|
|
308
|
+
|
|
309
|
+
// Update internal state for reactivity
|
|
310
|
+
internalValue = newStringValue;
|
|
311
|
+
|
|
312
|
+
// Update the input element value directly
|
|
313
|
+
if (inputElement) {
|
|
314
|
+
inputElement.value = newStringValue;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
// Trigger change events
|
|
318
|
+
onValueChange?.(newValue);
|
|
319
|
+
oninput?.(newStringValue);
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
/**
|
|
323
|
+
* Handles decrement button click
|
|
324
|
+
*/
|
|
325
|
+
const handleDecrement = () => {
|
|
326
|
+
if (!canDecrement) return;
|
|
327
|
+
|
|
328
|
+
const currentNum = numericValue;
|
|
329
|
+
let newValue = currentNum - step;
|
|
330
|
+
|
|
331
|
+
// Apply min constraint
|
|
332
|
+
if (min !== undefined && newValue < min) {
|
|
333
|
+
newValue = min;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
const newStringValue = newValue.toString();
|
|
337
|
+
|
|
338
|
+
// Update internal state for reactivity
|
|
339
|
+
internalValue = newStringValue;
|
|
340
|
+
|
|
341
|
+
// Update the input element value directly
|
|
342
|
+
if (inputElement) {
|
|
343
|
+
inputElement.value = newStringValue;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
// Trigger change events
|
|
347
|
+
onValueChange?.(newValue);
|
|
348
|
+
oninput?.(newStringValue);
|
|
349
|
+
};
|
|
350
|
+
|
|
175
351
|
/**
|
|
176
352
|
* Gets the tooltip background color based on alert type
|
|
177
353
|
*/
|
|
@@ -190,6 +366,78 @@
|
|
|
190
366
|
};
|
|
191
367
|
</script>
|
|
192
368
|
|
|
369
|
+
{#snippet inputField()}
|
|
370
|
+
<input
|
|
371
|
+
bind:this={inputElement}
|
|
372
|
+
{id}
|
|
373
|
+
class={inputClasses}
|
|
374
|
+
{placeholder}
|
|
375
|
+
{readonly}
|
|
376
|
+
{disabled}
|
|
377
|
+
{type}
|
|
378
|
+
{min}
|
|
379
|
+
{max}
|
|
380
|
+
{step}
|
|
381
|
+
maxlength={maxLength}
|
|
382
|
+
minlength={minLength}
|
|
383
|
+
value={currInputValue}
|
|
384
|
+
defaultValue={value}
|
|
385
|
+
oninput={handleInput}
|
|
386
|
+
onfocus={handleFocus}
|
|
387
|
+
onkeydown={handleKeydown}
|
|
388
|
+
onblur={handleBlur}
|
|
389
|
+
style="font-size: {fontSize}; color: {computedColor};"
|
|
390
|
+
{...restProps}
|
|
391
|
+
/>
|
|
392
|
+
{/snippet}
|
|
393
|
+
|
|
394
|
+
{#snippet inputWrapper()}
|
|
395
|
+
<div class={wrapperClasses} style="height: {height}; width: {width};" role="group">
|
|
396
|
+
{#if currInputValue && pill}
|
|
397
|
+
<span
|
|
398
|
+
class="pill"
|
|
399
|
+
class:blue={pill === 'blue'}
|
|
400
|
+
class:gray={pill === 'gray'}
|
|
401
|
+
bind:this={pillElement}
|
|
402
|
+
style="width: {pillWidth}px;"
|
|
403
|
+
></span>
|
|
404
|
+
{/if}
|
|
405
|
+
|
|
406
|
+
{@render inputField()}
|
|
407
|
+
|
|
408
|
+
{#if units && !showSteppers}
|
|
409
|
+
<div class="input-units-steppers">{units}</div>
|
|
410
|
+
{/if}
|
|
411
|
+
|
|
412
|
+
{#if showSteppers && !units}
|
|
413
|
+
<div class="input-units-steppers steppers">
|
|
414
|
+
<button
|
|
415
|
+
type="button"
|
|
416
|
+
class="stepper-button stepper-up"
|
|
417
|
+
disabled={!canIncrement}
|
|
418
|
+
onclick={handleIncrement}
|
|
419
|
+
aria-label="Increment value"
|
|
420
|
+
>
|
|
421
|
+
<span class="stepper-button-icon">⌃</span>
|
|
422
|
+
</button>
|
|
423
|
+
<button
|
|
424
|
+
type="button"
|
|
425
|
+
class="stepper-button stepper-down"
|
|
426
|
+
disabled={!canDecrement}
|
|
427
|
+
onclick={handleDecrement}
|
|
428
|
+
aria-label="Decrement value"
|
|
429
|
+
>
|
|
430
|
+
<span class="stepper-button-icon">⌃</span>
|
|
431
|
+
</button>
|
|
432
|
+
</div>
|
|
433
|
+
{/if}
|
|
434
|
+
|
|
435
|
+
{#if children}
|
|
436
|
+
{@render children()}
|
|
437
|
+
{/if}
|
|
438
|
+
</div>
|
|
439
|
+
{/snippet}
|
|
440
|
+
|
|
193
441
|
{#if hasAlert}
|
|
194
442
|
<Tooltip
|
|
195
443
|
message={alert?.message || ''}
|
|
@@ -206,85 +454,11 @@
|
|
|
206
454
|
class="input-tooltip"
|
|
207
455
|
>
|
|
208
456
|
{#snippet target()}
|
|
209
|
-
|
|
210
|
-
{#if currInputValue && pill}
|
|
211
|
-
<span
|
|
212
|
-
class="pill"
|
|
213
|
-
class:blue={pill === 'blue'}
|
|
214
|
-
class:gray={pill === 'gray'}
|
|
215
|
-
bind:this={pillElement}
|
|
216
|
-
style="width: {pillWidth}px;"
|
|
217
|
-
></span>
|
|
218
|
-
{/if}
|
|
219
|
-
|
|
220
|
-
<input
|
|
221
|
-
bind:this={inputElement}
|
|
222
|
-
{id}
|
|
223
|
-
class={inputClasses}
|
|
224
|
-
{placeholder}
|
|
225
|
-
{readonly}
|
|
226
|
-
{disabled}
|
|
227
|
-
{type}
|
|
228
|
-
maxlength={maxLength}
|
|
229
|
-
minlength={minLength}
|
|
230
|
-
value={currInputValue}
|
|
231
|
-
oninput={handleInput}
|
|
232
|
-
onfocus={handleFocus}
|
|
233
|
-
onkeydown={handleKeydown}
|
|
234
|
-
onblur={handleBlur}
|
|
235
|
-
style="font-size: {fontSize}; color: {computedColor};"
|
|
236
|
-
{...restProps}
|
|
237
|
-
/>
|
|
238
|
-
|
|
239
|
-
{#if units}
|
|
240
|
-
<div class="input-units">{units}</div>
|
|
241
|
-
{/if}
|
|
242
|
-
|
|
243
|
-
{#if children}
|
|
244
|
-
{@render children()}
|
|
245
|
-
{/if}
|
|
246
|
-
</div>
|
|
457
|
+
{@render inputWrapper()}
|
|
247
458
|
{/snippet}
|
|
248
459
|
</Tooltip>
|
|
249
460
|
{:else}
|
|
250
|
-
|
|
251
|
-
{#if currInputValue && pill}
|
|
252
|
-
<span
|
|
253
|
-
class="pill"
|
|
254
|
-
class:blue={pill === 'blue'}
|
|
255
|
-
class:gray={pill === 'gray'}
|
|
256
|
-
bind:this={pillElement}
|
|
257
|
-
style="width: {pillWidth}px;"
|
|
258
|
-
></span>
|
|
259
|
-
{/if}
|
|
260
|
-
|
|
261
|
-
<input
|
|
262
|
-
bind:this={inputElement}
|
|
263
|
-
{id}
|
|
264
|
-
class={inputClasses}
|
|
265
|
-
{placeholder}
|
|
266
|
-
{readonly}
|
|
267
|
-
{disabled}
|
|
268
|
-
{type}
|
|
269
|
-
maxlength={maxLength}
|
|
270
|
-
minlength={minLength}
|
|
271
|
-
value={currInputValue}
|
|
272
|
-
oninput={handleInput}
|
|
273
|
-
onfocus={handleFocus}
|
|
274
|
-
onkeydown={handleKeydown}
|
|
275
|
-
onblur={handleBlur}
|
|
276
|
-
style="font-size: {fontSize}; color: {computedColor};"
|
|
277
|
-
{...restProps}
|
|
278
|
-
/>
|
|
279
|
-
|
|
280
|
-
{#if units}
|
|
281
|
-
<div class="input-units">{units}</div>
|
|
282
|
-
{/if}
|
|
283
|
-
|
|
284
|
-
{#if children}
|
|
285
|
-
{@render children()}
|
|
286
|
-
{/if}
|
|
287
|
-
</div>
|
|
461
|
+
{@render inputWrapper()}
|
|
288
462
|
{/if}
|
|
289
463
|
|
|
290
464
|
<style>
|
|
@@ -324,10 +498,21 @@
|
|
|
324
498
|
grid-template-columns: 1fr auto;
|
|
325
499
|
padding: 0 0 0 4px;
|
|
326
500
|
}
|
|
501
|
+
|
|
502
|
+
.webflow-input-wrapper.steppers {
|
|
503
|
+
grid-template-columns: 1fr auto;
|
|
504
|
+
padding: 0 0 0 4px;
|
|
505
|
+
}
|
|
506
|
+
|
|
327
507
|
.webflow-input-wrapper.units .webflow-input {
|
|
328
508
|
padding-right: 4px;
|
|
329
509
|
}
|
|
330
|
-
|
|
510
|
+
|
|
511
|
+
.webflow-input-wrapper.steppers .webflow-input {
|
|
512
|
+
padding-right: 4px;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.input-units-steppers {
|
|
331
516
|
display: flex;
|
|
332
517
|
align-items: center;
|
|
333
518
|
justify-content: center;
|
|
@@ -346,6 +531,62 @@
|
|
|
346
531
|
text-align: center;
|
|
347
532
|
opacity: 0.75;
|
|
348
533
|
}
|
|
534
|
+
|
|
535
|
+
.input-units-steppers.steppers {
|
|
536
|
+
justify-content: center;
|
|
537
|
+
flex-direction: column;
|
|
538
|
+
width: 16px;
|
|
539
|
+
gap: 1px;
|
|
540
|
+
background-color: var(--border1);
|
|
541
|
+
margin-top: -2px;
|
|
542
|
+
margin-bottom: -2px;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
.stepper-button {
|
|
546
|
+
border: none;
|
|
547
|
+
width: 16px;
|
|
548
|
+
background-color: var(--actionSecondaryBackground);
|
|
549
|
+
color: var(--text2);
|
|
550
|
+
font-size: 0.8em;
|
|
551
|
+
line-height: 1;
|
|
552
|
+
height: 48%;
|
|
553
|
+
display: flex;
|
|
554
|
+
align-items: center;
|
|
555
|
+
justify-content: center;
|
|
556
|
+
padding: 0;
|
|
557
|
+
cursor: pointer;
|
|
558
|
+
transition: background-color 0.2s ease;
|
|
559
|
+
}
|
|
560
|
+
|
|
561
|
+
.stepper-button-icon {
|
|
562
|
+
width: 8px;
|
|
563
|
+
height: 5px;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
.stepper-button:hover:not(:disabled) {
|
|
567
|
+
background-color: var(--hoverColor);
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
.stepper-button:disabled {
|
|
571
|
+
opacity: 0.75;
|
|
572
|
+
cursor: not-allowed;
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
.stepper-up {
|
|
576
|
+
transform: rotate(0deg);
|
|
577
|
+
border-radius: 0 1px 0 0;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
.stepper-down {
|
|
581
|
+
transform: rotate(180deg);
|
|
582
|
+
border-radius: 1px 0 0 0;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
.stepper-button :global(svg) {
|
|
586
|
+
width: 16px;
|
|
587
|
+
height: 16px;
|
|
588
|
+
}
|
|
589
|
+
|
|
349
590
|
.webflow-input {
|
|
350
591
|
padding: 0;
|
|
351
592
|
margin: 0;
|
|
@@ -28,7 +28,8 @@ export interface InputProps extends Omit<HTMLInputAttributes, 'onblur' | 'onfocu
|
|
|
28
28
|
*/
|
|
29
29
|
color?: string;
|
|
30
30
|
/**
|
|
31
|
-
* Optional: If set it will add an element to the right of the input field and show the unit
|
|
31
|
+
* Optional: If set it will add an element to the right of the input field and show the unit.
|
|
32
|
+
* Cannot be used together with showSteppers
|
|
32
33
|
*/
|
|
33
34
|
units?: string;
|
|
34
35
|
/**
|
|
@@ -76,6 +77,23 @@ export interface InputProps extends Omit<HTMLInputAttributes, 'onblur' | 'onfocu
|
|
|
76
77
|
* Possible values: 'blue', 'gray', or null/undefined for no pill
|
|
77
78
|
*/
|
|
78
79
|
pill?: PillVariant;
|
|
80
|
+
/**
|
|
81
|
+
* Shows increment/decrement buttons for number inputs.
|
|
82
|
+
* Only available when type="number"
|
|
83
|
+
*/
|
|
84
|
+
showSteppers?: boolean;
|
|
85
|
+
/**
|
|
86
|
+
* Step value for increment/decrement buttons.
|
|
87
|
+
*/
|
|
88
|
+
step?: number;
|
|
89
|
+
/**
|
|
90
|
+
* Minimum value for number input.
|
|
91
|
+
*/
|
|
92
|
+
min?: number;
|
|
93
|
+
/**
|
|
94
|
+
* Maximum value for number input.
|
|
95
|
+
*/
|
|
96
|
+
max?: number;
|
|
79
97
|
/**
|
|
80
98
|
* Event handler for input changes - receives the trimmed string value
|
|
81
99
|
*/
|
|
@@ -92,6 +110,11 @@ export interface InputProps extends Omit<HTMLInputAttributes, 'onblur' | 'onfocu
|
|
|
92
110
|
* Event handler for keydown events - receives the standard KeyboardEvent
|
|
93
111
|
*/
|
|
94
112
|
onkeydown?: (event: KeyboardEvent) => void;
|
|
113
|
+
/**
|
|
114
|
+
* Event handler for numeric value changes - receives the numeric value
|
|
115
|
+
* Only called when showSteppers is true and value is a valid number
|
|
116
|
+
*/
|
|
117
|
+
onValueChange?: (value: number) => void;
|
|
95
118
|
/**
|
|
96
119
|
* Additional CSS classes
|
|
97
120
|
*/
|
|
@@ -107,3 +130,6 @@ export interface InputEvent {
|
|
|
107
130
|
export interface BlurEvent {
|
|
108
131
|
value: string;
|
|
109
132
|
}
|
|
133
|
+
export interface NumericValueChangeEvent {
|
|
134
|
+
value: number;
|
|
135
|
+
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
<script module lang="ts">
|
|
2
2
|
import { defineMeta } from '@storybook/addon-svelte-csf';
|
|
3
3
|
|
|
4
|
-
import
|
|
4
|
+
import { Wrapper } from './examples';
|
|
5
5
|
|
|
6
6
|
const { Story } = defineMeta({
|
|
7
7
|
title: 'UI/Layout',
|
|
8
|
-
component:
|
|
8
|
+
component: Wrapper,
|
|
9
9
|
tags: ['autodocs'],
|
|
10
10
|
parameters: {
|
|
11
11
|
layout: 'centered',
|
|
@@ -20,5 +20,5 @@
|
|
|
20
20
|
</script>
|
|
21
21
|
|
|
22
22
|
<Story name="Default">
|
|
23
|
-
<
|
|
23
|
+
<Wrapper />
|
|
24
24
|
</Story>
|