lapikit 0.7.3 → 0.7.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/@types/components.d.ts +1 -7
- package/dist/@types/dom.d.ts +4 -3
- package/dist/@types/props.d.ts +3 -3
- package/dist/animations/ripple.js +8 -2
- package/dist/components/accordion/accordion.svelte +192 -228
- package/dist/components/accordion/accordion.types.d.ts +5 -7
- package/dist/components/accordion/modules/accordion-item.svelte +144 -140
- package/dist/components/alert/alert.svelte +246 -293
- package/dist/components/alert/alert.types.d.ts +5 -5
- package/dist/components/app/app.svelte +25 -43
- package/dist/components/appbar/appbar.svelte +205 -190
- package/dist/components/appbar/appbar.types.d.ts +6 -6
- package/dist/components/aspect-ratio/aspect-ratio.svelte +43 -63
- package/dist/components/avatar/avatar.svelte +169 -161
- package/dist/components/avatar/avatar.types.d.ts +3 -4
- package/dist/components/btn/btn.svelte +432 -466
- package/dist/components/btn/btn.types.d.ts +5 -6
- package/dist/components/card/card.svelte +24 -23
- package/dist/components/card/card.types.d.ts +2 -2
- package/dist/components/card/modules/card-content.svelte +4 -1
- package/dist/components/card/modules/card-title.svelte +4 -1
- package/dist/components/chip/chip.svelte +416 -464
- package/dist/components/chip/chip.types.d.ts +5 -5
- package/dist/components/dialog/dialog.svelte +184 -175
- package/dist/components/dialog/dialog.types.d.ts +6 -6
- package/dist/components/dropdown/dropdown.svelte +149 -144
- package/dist/components/dropdown/dropdown.types.d.ts +4 -11
- package/dist/components/field/field.svelte +474 -0
- package/dist/components/field/field.svelte.d.ts +4 -0
- package/dist/components/field/field.types.d.ts +46 -0
- package/dist/components/field/field.types.js +1 -0
- package/dist/components/icon/icon.svelte +67 -96
- package/dist/components/icon/icon.types.d.ts +2 -1
- package/dist/components/index.d.ts +2 -0
- package/dist/components/index.js +1 -0
- package/dist/components/list/list.svelte +193 -194
- package/dist/components/list/list.types.d.ts +5 -7
- package/dist/components/list/modules/list-item.svelte +134 -147
- package/dist/components/modal/modal.js +9 -9
- package/dist/components/modal/modal.svelte +239 -222
- package/dist/components/modal/modal.types.d.ts +6 -6
- package/dist/components/popover/popover.svelte +125 -127
- package/dist/components/popover/popover.types.d.ts +4 -11
- package/dist/components/separator/separator.svelte +56 -87
- package/dist/components/separator/separator.types.d.ts +1 -1
- package/dist/components/spacer/spacer.svelte +6 -25
- package/dist/components/textfield/textfield.svelte +94 -543
- package/dist/components/textfield/textfield.types.d.ts +13 -33
- package/dist/components/toolbar/toolbar.svelte +216 -211
- package/dist/components/toolbar/toolbar.types.d.ts +8 -9
- package/dist/components/tooltip/tooltip.svelte +201 -266
- package/dist/components/tooltip/tooltip.types.d.ts +3 -10
- package/dist/constants.js +1 -0
- package/dist/escaping.js +0 -1
- package/dist/html-mapped.d.ts +1 -15
- package/dist/html-mapped.js +0 -19
- package/dist/labs/sheet/sheet.svelte +27 -22
- package/dist/utils/color.d.ts +2 -2
- package/dist/utils/color.js +2 -1
- package/dist/utils/components.d.ts +10 -10
- package/dist/utils/components.js +16 -75
- package/dist/utils/floating.d.ts +58 -0
- package/dist/utils/floating.js +131 -0
- package/dist/utils/index.d.ts +1 -0
- package/dist/utils/index.js +1 -0
- package/dist/utils/outside.d.ts +3 -1
- package/dist/utils/outside.js +15 -3
- package/package.json +6 -3
- package/dist/components/dropdown/dropdown.svelte.js +0 -148
- package/dist/components/popover/popover.svelte.js +0 -134
- package/dist/components/tooltip/tooltip.svelte.js +0 -131
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
{@render children?.()}
|
|
73
73
|
</svelte:element>
|
|
74
74
|
|
|
75
|
-
<style
|
|
75
|
+
<style>:where(.kit-sheet) {
|
|
76
76
|
--kit-sheet-color: initial;
|
|
77
77
|
--kit-sheet-on-color: initial;
|
|
78
78
|
--kit-sheet-active-fg: initial;
|
|
@@ -93,12 +93,15 @@
|
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
95
|
@supports (color: color(from red srgb-linear r g b)) {
|
|
96
|
-
.kit-sheet {
|
|
96
|
+
:where(.kit-sheet) {
|
|
97
97
|
--kit-sheet-contrast: color(from var(--kit-sheet-color) srgb-linear clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 100000, 1) clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 100000, 1) clamp(0, (0.1791 - (0.2126 * r + 0.7152 * g + 0.0722 * b)) * 100000, 1)/1);
|
|
98
98
|
}
|
|
99
99
|
}
|
|
100
|
-
.kit-sheet {
|
|
100
|
+
:where(.kit-sheet) {
|
|
101
101
|
--kit-sheet-p: 12px;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
.kit-sheet {
|
|
102
105
|
display: flex;
|
|
103
106
|
position: relative;
|
|
104
107
|
gap: calc(var(--kit-space-default) + var(--kit-sheet-density-offset) / 2);
|
|
@@ -129,7 +132,7 @@ button.kit-sheet {
|
|
|
129
132
|
text-align: inherit;
|
|
130
133
|
}
|
|
131
134
|
|
|
132
|
-
.kit-sheet[data-variant=tonal] {
|
|
135
|
+
:where(.kit-sheet[data-variant=tonal]) {
|
|
133
136
|
--kit-sheet-bg: color-mix(in oklab, var(--kit-sheet-ink) 16%, transparent);
|
|
134
137
|
--kit-sheet-fg: var(--kit-sheet-ink);
|
|
135
138
|
--kit-sheet-border: transparent;
|
|
@@ -137,7 +140,7 @@ button.kit-sheet {
|
|
|
137
140
|
--kit-sheet-active-fg: var(--kit-sheet-ink);
|
|
138
141
|
}
|
|
139
142
|
|
|
140
|
-
.kit-sheet[data-variant=text] {
|
|
143
|
+
:where(.kit-sheet[data-variant=text]) {
|
|
141
144
|
--kit-sheet-bg: transparent;
|
|
142
145
|
--kit-sheet-fg: var(--kit-sheet-ink);
|
|
143
146
|
--kit-sheet-border: transparent;
|
|
@@ -145,7 +148,7 @@ button.kit-sheet {
|
|
|
145
148
|
--kit-sheet-active-fg: var(--kit-sheet-ink);
|
|
146
149
|
}
|
|
147
150
|
|
|
148
|
-
.kit-sheet[data-variant=plain] {
|
|
151
|
+
:where(.kit-sheet[data-variant=plain]) {
|
|
149
152
|
--kit-sheet-bg: transparent;
|
|
150
153
|
--kit-sheet-fg: var(--kit-sheet-ink);
|
|
151
154
|
--kit-sheet-border: transparent;
|
|
@@ -157,25 +160,27 @@ button.kit-sheet {
|
|
|
157
160
|
--kit-sheet-active-fg: var(--kit-sheet-color, var(--kit-color-accent));
|
|
158
161
|
}
|
|
159
162
|
|
|
160
|
-
.kit-sheet[data-variant=outline] {
|
|
163
|
+
:where(.kit-sheet[data-variant=outline]) {
|
|
161
164
|
--kit-sheet-bg: transparent;
|
|
162
165
|
--kit-sheet-fg: var(--kit-sheet-ink);
|
|
163
166
|
--kit-sheet-border: var(--kit-sheet-color, var(--kit-color-border));
|
|
164
167
|
--kit-sheet-active: color-mix(in oklab, var(--kit-sheet-ink) 14%, transparent);
|
|
165
168
|
--kit-sheet-active-fg: var(--kit-sheet-ink);
|
|
166
|
-
border: var(--kit-outline-weight) solid var(--kit-sheet-border);
|
|
167
169
|
}
|
|
168
170
|
|
|
169
|
-
.kit-sheet[data-variant=surface] {
|
|
171
|
+
:where(.kit-sheet[data-variant=surface]) {
|
|
170
172
|
--kit-sheet-bg: color-mix(in oklab, var(--kit-sheet-ink) 8%, transparent);
|
|
171
173
|
--kit-sheet-fg: var(--kit-sheet-ink);
|
|
172
174
|
--kit-sheet-border: color-mix(in oklab, var(--kit-sheet-ink) 35%, transparent);
|
|
173
175
|
--kit-sheet-active: color-mix(in oklab, var(--kit-sheet-ink) 18%, transparent);
|
|
174
176
|
--kit-sheet-active-fg: var(--kit-sheet-ink);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.kit-sheet:is([data-variant=outline], [data-variant=surface]) {
|
|
175
180
|
border: var(--kit-outline-weight) solid var(--kit-sheet-border);
|
|
176
181
|
}
|
|
177
182
|
|
|
178
|
-
.kit-sheet[data-active=true] {
|
|
183
|
+
:where(.kit-sheet[data-active=true]) {
|
|
179
184
|
--kit-sheet-bg: var(--kit-sheet-active, var(--kit-color-accent));
|
|
180
185
|
--kit-sheet-fg: var(
|
|
181
186
|
--kit-sheet-active-fg,
|
|
@@ -213,31 +218,31 @@ button.kit-sheet {
|
|
|
213
218
|
* rounded
|
|
214
219
|
* @link https://lapikit.dev/docs/customize
|
|
215
220
|
*/
|
|
216
|
-
.kit-sheet[data-rounded="0"] {
|
|
221
|
+
:where(.kit-sheet[data-rounded="0"]) {
|
|
217
222
|
--kit-sheet-radius: var(--kit-shape-none);
|
|
218
223
|
}
|
|
219
224
|
|
|
220
|
-
.kit-sheet[data-rounded=xs] {
|
|
225
|
+
:where(.kit-sheet[data-rounded=xs]) {
|
|
221
226
|
--kit-sheet-radius: var(--kit-shape-xs);
|
|
222
227
|
}
|
|
223
228
|
|
|
224
|
-
.kit-sheet[data-rounded=sm] {
|
|
229
|
+
:where(.kit-sheet[data-rounded=sm]) {
|
|
225
230
|
--kit-sheet-radius: var(--kit-shape-sm);
|
|
226
231
|
}
|
|
227
232
|
|
|
228
|
-
.kit-sheet[data-rounded=md] {
|
|
233
|
+
:where(.kit-sheet[data-rounded=md]) {
|
|
229
234
|
--kit-sheet-radius: var(--kit-shape-md);
|
|
230
235
|
}
|
|
231
236
|
|
|
232
|
-
.kit-sheet[data-rounded=lg] {
|
|
237
|
+
:where(.kit-sheet[data-rounded=lg]) {
|
|
233
238
|
--kit-sheet-radius: var(--kit-shape-lg);
|
|
234
239
|
}
|
|
235
240
|
|
|
236
|
-
.kit-sheet[data-rounded=xl] {
|
|
241
|
+
:where(.kit-sheet[data-rounded=xl]) {
|
|
237
242
|
--kit-sheet-radius: var(--kit-shape-xl);
|
|
238
243
|
}
|
|
239
244
|
|
|
240
|
-
.kit-sheet[data-rounded=full] {
|
|
245
|
+
:where(.kit-sheet[data-rounded=full]) {
|
|
241
246
|
--kit-sheet-radius: var(--kit-shape-full);
|
|
242
247
|
}
|
|
243
248
|
|
|
@@ -245,22 +250,22 @@ button.kit-sheet {
|
|
|
245
250
|
* density
|
|
246
251
|
* @link https://lapikit.dev/docs/customize
|
|
247
252
|
*/
|
|
248
|
-
.kit-sheet[data-density=dense] {
|
|
253
|
+
:where(.kit-sheet[data-density=dense]) {
|
|
249
254
|
--kit-sheet-density-offset: var(--kit-density-dense);
|
|
250
255
|
}
|
|
251
256
|
|
|
252
|
-
.kit-sheet[data-density=compact] {
|
|
257
|
+
:where(.kit-sheet[data-density=compact]) {
|
|
253
258
|
--kit-sheet-density-offset: var(--kit-density-compact);
|
|
254
259
|
}
|
|
255
260
|
|
|
256
|
-
.kit-sheet[data-density=default] {
|
|
261
|
+
:where(.kit-sheet[data-density=default]) {
|
|
257
262
|
--kit-sheet-density-offset: var(--kit-density-default);
|
|
258
263
|
}
|
|
259
264
|
|
|
260
|
-
.kit-sheet[data-density=comfortable] {
|
|
265
|
+
:where(.kit-sheet[data-density=comfortable]) {
|
|
261
266
|
--kit-sheet-density-offset: var(--kit-density-comfortable);
|
|
262
267
|
}
|
|
263
268
|
|
|
264
|
-
.kit-sheet[data-density=spacious] {
|
|
269
|
+
:where(.kit-sheet[data-density=spacious]) {
|
|
265
270
|
--kit-sheet-density-offset: var(--kit-density-spacious);
|
|
266
271
|
}</style>
|
package/dist/utils/color.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { ColorProps } from '../@types';
|
|
2
|
-
export declare function resolveColor(color: string | null | undefined): string | undefined;
|
|
3
|
-
export declare function resolveOnColor(color: string | null | undefined): string | undefined;
|
|
2
|
+
export declare function resolveColor(color: string | false | null | undefined): string | undefined;
|
|
3
|
+
export declare function resolveOnColor(color: string | false | null | undefined): string | undefined;
|
|
4
4
|
export declare function colorStyle(name: string, color: ColorProps | null | undefined, active?: boolean): string;
|
package/dist/utils/color.js
CHANGED
|
@@ -2,7 +2,8 @@ import { DEV } from 'esm-env';
|
|
|
2
2
|
const paletteName = /^[a-zA-Z][\w-]*$/;
|
|
3
3
|
const unsafe = /[;{}]/;
|
|
4
4
|
function clean(color) {
|
|
5
|
-
|
|
5
|
+
// color={isActive && 'accent'} gives false: only a string is a color
|
|
6
|
+
const value = typeof color === 'string' ? color.trim() : undefined;
|
|
6
7
|
if (!value)
|
|
7
8
|
return undefined;
|
|
8
9
|
if (unsafe.test(value)) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ColorProps, ComponentAttrs, ElevationProps, ElevationState, PropValue, SStyleProp,
|
|
1
|
+
import type { ColorProps, ComponentAttrs, ElevationProps, ElevationState, PropValue, SStyleProp, useStylesProps } from '../@types';
|
|
2
2
|
import type { ClassValue } from 'svelte/elements';
|
|
3
3
|
/**
|
|
4
4
|
* The classes of the s-class_xxx directives (class:xxx on a kit tag):
|
|
@@ -9,15 +9,6 @@ import type { ClassValue } from 'svelte/elements';
|
|
|
9
9
|
* - false, null, undefined and '' give nothing.
|
|
10
10
|
*/
|
|
11
11
|
export declare function directiveClasses(classProps: Record<string, PropValue> | undefined): string[];
|
|
12
|
-
/**
|
|
13
|
-
* useClassName - Utility to compute class names for a component.
|
|
14
|
-
* @param baseClass - The base class name for the component.
|
|
15
|
-
* @param className - Additional class names: a string or an array of strings.
|
|
16
|
-
* @param sClass - The s-class property which can be a string, array, or object.
|
|
17
|
-
* @param classProps - An object containing s-class_xxx directives.
|
|
18
|
-
* @returns A computed class string: no extra spaces, no duplicates, in the order of the inputs.
|
|
19
|
-
*/
|
|
20
|
-
export declare function useClassName({ baseClass, className, sClass, classProps }?: useClassNameProps): string;
|
|
21
12
|
export declare function useIsInteractive(props: Record<string, unknown>, tag: string, interactiveTags: readonly string[], interactive?: boolean): boolean;
|
|
22
13
|
/**
|
|
23
14
|
* useStyles - Utility to compute style declarations for a component (pure function).
|
|
@@ -58,3 +49,12 @@ export declare function useComponentAttrs(baseClass: string, { className, sClass
|
|
|
58
49
|
color?: ColorProps | null;
|
|
59
50
|
active?: boolean;
|
|
60
51
|
}, rest: Record<string, unknown>): ComponentAttrs;
|
|
52
|
+
/**
|
|
53
|
+
* splitAriaAttrs - Separates the aria-* attributes from the other attributes, for a component whose
|
|
54
|
+
* role is on another element than its content (dialog, modal).
|
|
55
|
+
* @param rest - The rest of the props of the component.
|
|
56
|
+
*/
|
|
57
|
+
export declare function splitAriaAttrs(rest: Record<string, unknown>): {
|
|
58
|
+
aria: Record<string, unknown>;
|
|
59
|
+
others: Record<string, unknown>;
|
|
60
|
+
};
|
package/dist/utils/components.js
CHANGED
|
@@ -3,8 +3,6 @@ import { makeComponentProps } from '../html-mapped';
|
|
|
3
3
|
import { colorStyle } from './color.js';
|
|
4
4
|
const endsWithSeparator = /[^a-zA-Z0-9]$/;
|
|
5
5
|
const startsWithSeparator = /^[^a-zA-Z0-9]/;
|
|
6
|
-
const whitespace = /\s/;
|
|
7
|
-
const whitespaces = /\s+/;
|
|
8
6
|
const propertyCache = new Map();
|
|
9
7
|
function hasKeys(value) {
|
|
10
8
|
if (!value || typeof value !== 'object')
|
|
@@ -15,39 +13,6 @@ function hasKeys(value) {
|
|
|
15
13
|
}
|
|
16
14
|
return false;
|
|
17
15
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Adds the classes of a value (one or several, separated by spaces) to the set.
|
|
20
|
-
* The set keeps the first position of each class and drops the duplicates.
|
|
21
|
-
*/
|
|
22
|
-
function addClasses(classes, value) {
|
|
23
|
-
if (!whitespace.test(value)) {
|
|
24
|
-
if (value)
|
|
25
|
-
classes.add(value);
|
|
26
|
-
return;
|
|
27
|
-
}
|
|
28
|
-
for (const name of value.split(whitespaces)) {
|
|
29
|
-
if (name)
|
|
30
|
-
classes.add(name);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
/**
|
|
34
|
-
* Adds a class value with the rules of clsx (class on an element): a string, an array (nested too),
|
|
35
|
-
* or an object whose keys are added when their value is truthy. Joining an array would give "a,b"
|
|
36
|
-
*/
|
|
37
|
-
function addClassValue(classes, value) {
|
|
38
|
-
if (typeof value === 'string')
|
|
39
|
-
addClasses(classes, value);
|
|
40
|
-
else if (Array.isArray(value)) {
|
|
41
|
-
for (const item of value)
|
|
42
|
-
addClassValue(classes, item);
|
|
43
|
-
}
|
|
44
|
-
else if (value && typeof value === 'object') {
|
|
45
|
-
for (const key in value) {
|
|
46
|
-
if (value[key])
|
|
47
|
-
addClasses(classes, key);
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
16
|
/**
|
|
52
17
|
* The classes of the s-class_xxx directives (class:xxx on a kit tag):
|
|
53
18
|
* - true gives the name (class:active -> active);
|
|
@@ -74,46 +39,6 @@ export function directiveClasses(classProps) {
|
|
|
74
39
|
}
|
|
75
40
|
return classes;
|
|
76
41
|
}
|
|
77
|
-
/**
|
|
78
|
-
* useClassName - Utility to compute class names for a component.
|
|
79
|
-
* @param baseClass - The base class name for the component.
|
|
80
|
-
* @param className - Additional class names: a string or an array of strings.
|
|
81
|
-
* @param sClass - The s-class property which can be a string, array, or object.
|
|
82
|
-
* @param classProps - An object containing s-class_xxx directives.
|
|
83
|
-
* @returns A computed class string: no extra spaces, no duplicates, in the order of the inputs.
|
|
84
|
-
*/
|
|
85
|
-
export function useClassName({ baseClass = '', className, sClass, classProps } = {}) {
|
|
86
|
-
if (!sClass && !className && !hasKeys(classProps))
|
|
87
|
-
return baseClass;
|
|
88
|
-
const classes = new Set();
|
|
89
|
-
if (baseClass)
|
|
90
|
-
addClasses(classes, baseClass);
|
|
91
|
-
if (typeof sClass === 'string') {
|
|
92
|
-
addClasses(classes, sClass);
|
|
93
|
-
}
|
|
94
|
-
else if (Array.isArray(sClass)) {
|
|
95
|
-
for (const value of sClass) {
|
|
96
|
-
if (typeof value === 'string')
|
|
97
|
-
addClasses(classes, value);
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
else if (sClass && typeof sClass === 'object') {
|
|
101
|
-
for (const key in sClass) {
|
|
102
|
-
const value = sClass[key];
|
|
103
|
-
if (value === true)
|
|
104
|
-
addClasses(classes, key);
|
|
105
|
-
else if (typeof value === 'string')
|
|
106
|
-
addClasses(classes, value);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
if (classProps) {
|
|
110
|
-
for (const name of directiveClasses(classProps))
|
|
111
|
-
addClasses(classes, name);
|
|
112
|
-
}
|
|
113
|
-
if (className)
|
|
114
|
-
addClassValue(classes, className);
|
|
115
|
-
return [...classes].join(' ');
|
|
116
|
-
}
|
|
117
42
|
/**
|
|
118
43
|
* useIsInteractive - Utility to determine whether a component should behave as interactive:
|
|
119
44
|
* either explicitly flagged, rendered as an interactive tag (e.g. 'a', 'button'), or given
|
|
@@ -243,3 +168,19 @@ export function useComponentAttrs(baseClass, { className, sClass, styleAttr, sSt
|
|
|
243
168
|
rest: restProps
|
|
244
169
|
};
|
|
245
170
|
}
|
|
171
|
+
/**
|
|
172
|
+
* splitAriaAttrs - Separates the aria-* attributes from the other attributes, for a component whose
|
|
173
|
+
* role is on another element than its content (dialog, modal).
|
|
174
|
+
* @param rest - The rest of the props of the component.
|
|
175
|
+
*/
|
|
176
|
+
export function splitAriaAttrs(rest) {
|
|
177
|
+
const aria = {};
|
|
178
|
+
const others = {};
|
|
179
|
+
for (const key in rest) {
|
|
180
|
+
if (key.startsWith('aria-'))
|
|
181
|
+
aria[key] = rest[key];
|
|
182
|
+
else
|
|
183
|
+
others[key] = rest[key];
|
|
184
|
+
}
|
|
185
|
+
return { aria, others };
|
|
186
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export type FloatingSide = 'top' | 'bottom' | 'left' | 'right';
|
|
2
|
+
export type FloatingAlign = 'start' | 'center' | 'end';
|
|
3
|
+
/** An element, or a point of the viewport (the position of a pointer event) */
|
|
4
|
+
export type FloatingAnchor = HTMLElement | {
|
|
5
|
+
x: number;
|
|
6
|
+
y: number;
|
|
7
|
+
};
|
|
8
|
+
export interface FloatingOptions {
|
|
9
|
+
anchor: FloatingAnchor | null | undefined;
|
|
10
|
+
/** false hides the element without removing it (default true) */
|
|
11
|
+
open?: boolean;
|
|
12
|
+
side?: FloatingSide;
|
|
13
|
+
align?: FloatingAlign;
|
|
14
|
+
/** space between the anchor and the floating element, in px */
|
|
15
|
+
offset?: number;
|
|
16
|
+
/** minimal space between the floating element and the edges of the viewport, in px */
|
|
17
|
+
padding?: number;
|
|
18
|
+
/** moves to the opposite side when there is not enough space */
|
|
19
|
+
flip?: boolean;
|
|
20
|
+
}
|
|
21
|
+
export interface FloatingRect {
|
|
22
|
+
top: number;
|
|
23
|
+
right: number;
|
|
24
|
+
bottom: number;
|
|
25
|
+
left: number;
|
|
26
|
+
width: number;
|
|
27
|
+
height: number;
|
|
28
|
+
}
|
|
29
|
+
export interface FloatingPosition {
|
|
30
|
+
x: number;
|
|
31
|
+
y: number;
|
|
32
|
+
side: FloatingSide;
|
|
33
|
+
/** position of the center of the anchor along the floating element, for an arrow */
|
|
34
|
+
arrow: number;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* computeFloating - The position of a floating element next to an anchor (pure function).
|
|
38
|
+
* @param anchor - The rect of the anchor, in the viewport.
|
|
39
|
+
* @param size - The size of the floating element (offsetWidth / offsetHeight: not affected by a transform).
|
|
40
|
+
* @param viewport - The size of the viewport, without the scrollbars.
|
|
41
|
+
*/
|
|
42
|
+
export declare function computeFloating(anchor: FloatingRect, size: {
|
|
43
|
+
width: number;
|
|
44
|
+
height: number;
|
|
45
|
+
}, viewport: {
|
|
46
|
+
width: number;
|
|
47
|
+
height: number;
|
|
48
|
+
}, { side, align, offset, padding, flip }?: Omit<FloatingOptions, 'anchor'>): FloatingPosition;
|
|
49
|
+
/**
|
|
50
|
+
* floating - Shows an element in the top layer (Popover API) next to its anchor, and keeps it there.
|
|
51
|
+
* The element needs the popover attribute. It gets its position (left / top), its side (data-side)
|
|
52
|
+
* and the position of the arrow (--kit-floating-arrow).
|
|
53
|
+
* It follows the scroll of every ancestor, the resize of the viewport and the size of both elements.
|
|
54
|
+
*/
|
|
55
|
+
export declare function floating(node: HTMLElement, options: FloatingOptions): {
|
|
56
|
+
update(next: FloatingOptions): void;
|
|
57
|
+
destroy(): void;
|
|
58
|
+
};
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
const opposite = {
|
|
2
|
+
top: 'bottom',
|
|
3
|
+
bottom: 'top',
|
|
4
|
+
left: 'right',
|
|
5
|
+
right: 'left'
|
|
6
|
+
};
|
|
7
|
+
function clamp(value, min, max) {
|
|
8
|
+
return Math.min(Math.max(value, min), Math.max(min, max));
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* computeFloating - The position of a floating element next to an anchor (pure function).
|
|
12
|
+
* @param anchor - The rect of the anchor, in the viewport.
|
|
13
|
+
* @param size - The size of the floating element (offsetWidth / offsetHeight: not affected by a transform).
|
|
14
|
+
* @param viewport - The size of the viewport, without the scrollbars.
|
|
15
|
+
*/
|
|
16
|
+
export function computeFloating(anchor, size, viewport, { side = 'bottom', align = 'start', offset = 6, padding = 8, flip = true } = {}) {
|
|
17
|
+
const space = {
|
|
18
|
+
top: anchor.top - offset - padding,
|
|
19
|
+
bottom: viewport.height - anchor.bottom - offset - padding,
|
|
20
|
+
left: anchor.left - offset - padding,
|
|
21
|
+
right: viewport.width - anchor.right - offset - padding
|
|
22
|
+
};
|
|
23
|
+
const vertical = side === 'top' || side === 'bottom';
|
|
24
|
+
const needed = vertical ? size.height : size.width;
|
|
25
|
+
let resolvedSide = side;
|
|
26
|
+
if (flip && space[side] < needed && space[opposite[side]] > space[side]) {
|
|
27
|
+
resolvedSide = opposite[side];
|
|
28
|
+
}
|
|
29
|
+
let x;
|
|
30
|
+
let y;
|
|
31
|
+
if (vertical) {
|
|
32
|
+
y = resolvedSide === 'top' ? anchor.top - offset - size.height : anchor.bottom + offset;
|
|
33
|
+
x =
|
|
34
|
+
align === 'start'
|
|
35
|
+
? anchor.left
|
|
36
|
+
: align === 'end'
|
|
37
|
+
? anchor.right - size.width
|
|
38
|
+
: anchor.left + (anchor.width - size.width) / 2;
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
x = resolvedSide === 'left' ? anchor.left - offset - size.width : anchor.right + offset;
|
|
42
|
+
y =
|
|
43
|
+
align === 'start'
|
|
44
|
+
? anchor.top
|
|
45
|
+
: align === 'end'
|
|
46
|
+
? anchor.bottom - size.height
|
|
47
|
+
: anchor.top + (anchor.height - size.height) / 2;
|
|
48
|
+
}
|
|
49
|
+
// shift: the floating element stays in the viewport
|
|
50
|
+
x = clamp(x, padding, viewport.width - size.width - padding);
|
|
51
|
+
y = clamp(y, padding, viewport.height - size.height - padding);
|
|
52
|
+
const arrow = vertical
|
|
53
|
+
? clamp(anchor.left + anchor.width / 2 - x, 8, size.width - 8)
|
|
54
|
+
: clamp(anchor.top + anchor.height / 2 - y, 8, size.height - 8);
|
|
55
|
+
return { x, y, side: resolvedSide, arrow };
|
|
56
|
+
}
|
|
57
|
+
function anchorRect(anchor) {
|
|
58
|
+
if (anchor instanceof HTMLElement)
|
|
59
|
+
return anchor.getBoundingClientRect();
|
|
60
|
+
return { top: anchor.y, right: anchor.x, bottom: anchor.y, left: anchor.x, width: 0, height: 0 };
|
|
61
|
+
}
|
|
62
|
+
function supportsPopover(node) {
|
|
63
|
+
return typeof node.showPopover === 'function';
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* floating - Shows an element in the top layer (Popover API) next to its anchor, and keeps it there.
|
|
67
|
+
* The element needs the popover attribute. It gets its position (left / top), its side (data-side)
|
|
68
|
+
* and the position of the arrow (--kit-floating-arrow).
|
|
69
|
+
* It follows the scroll of every ancestor, the resize of the viewport and the size of both elements.
|
|
70
|
+
*/
|
|
71
|
+
export function floating(node, options) {
|
|
72
|
+
let frame = 0;
|
|
73
|
+
function toggle() {
|
|
74
|
+
if (!supportsPopover(node))
|
|
75
|
+
return;
|
|
76
|
+
const shown = node.matches(':popover-open');
|
|
77
|
+
if (options.open !== false && !shown)
|
|
78
|
+
node.showPopover();
|
|
79
|
+
if (options.open === false && shown)
|
|
80
|
+
node.hidePopover();
|
|
81
|
+
}
|
|
82
|
+
function update() {
|
|
83
|
+
const { anchor, open, ...rest } = options;
|
|
84
|
+
if (open === false || !anchor || !node.isConnected)
|
|
85
|
+
return;
|
|
86
|
+
if (anchor instanceof HTMLElement && !anchor.isConnected)
|
|
87
|
+
return;
|
|
88
|
+
const position = computeFloating(anchorRect(anchor), { width: node.offsetWidth, height: node.offsetHeight }, {
|
|
89
|
+
width: document.documentElement.clientWidth,
|
|
90
|
+
height: document.documentElement.clientHeight
|
|
91
|
+
}, rest);
|
|
92
|
+
node.style.left = `${position.x}px`;
|
|
93
|
+
node.style.top = `${position.y}px`;
|
|
94
|
+
node.style.setProperty('--kit-floating-arrow', `${position.arrow}px`);
|
|
95
|
+
node.dataset.side = position.side;
|
|
96
|
+
}
|
|
97
|
+
function schedule() {
|
|
98
|
+
cancelAnimationFrame(frame);
|
|
99
|
+
frame = requestAnimationFrame(update);
|
|
100
|
+
}
|
|
101
|
+
toggle();
|
|
102
|
+
update();
|
|
103
|
+
// capture: the scroll of any ancestor, not only the window
|
|
104
|
+
window.addEventListener('scroll', schedule, { capture: true, passive: true });
|
|
105
|
+
window.addEventListener('resize', schedule, { passive: true });
|
|
106
|
+
const observer = typeof ResizeObserver === 'undefined' ? null : new ResizeObserver(schedule);
|
|
107
|
+
observer?.observe(node);
|
|
108
|
+
if (options.anchor instanceof HTMLElement)
|
|
109
|
+
observer?.observe(options.anchor);
|
|
110
|
+
return {
|
|
111
|
+
update(next) {
|
|
112
|
+
if (next.anchor !== options.anchor) {
|
|
113
|
+
if (options.anchor instanceof HTMLElement)
|
|
114
|
+
observer?.unobserve(options.anchor);
|
|
115
|
+
if (next.anchor instanceof HTMLElement)
|
|
116
|
+
observer?.observe(next.anchor);
|
|
117
|
+
}
|
|
118
|
+
options = next;
|
|
119
|
+
toggle();
|
|
120
|
+
schedule();
|
|
121
|
+
},
|
|
122
|
+
destroy() {
|
|
123
|
+
cancelAnimationFrame(frame);
|
|
124
|
+
window.removeEventListener('scroll', schedule, { capture: true });
|
|
125
|
+
window.removeEventListener('resize', schedule);
|
|
126
|
+
observer?.disconnect();
|
|
127
|
+
if (supportsPopover(node) && node.matches(':popover-open'))
|
|
128
|
+
node.hidePopover();
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
package/dist/utils/index.d.ts
CHANGED
package/dist/utils/index.js
CHANGED
package/dist/utils/outside.d.ts
CHANGED
|
@@ -3,4 +3,6 @@ export declare function clickOutside(node: HTMLElement, options: ClickOutsideOpt
|
|
|
3
3
|
update(newOptions: ClickOutsideOptions): void;
|
|
4
4
|
destroy(): void;
|
|
5
5
|
};
|
|
6
|
-
|
|
6
|
+
/** Blocks the scroll of the page; each call needs its own unlockScroll() */
|
|
7
|
+
export declare function lockScroll(): void;
|
|
8
|
+
export declare function unlockScroll(): void;
|
package/dist/utils/outside.js
CHANGED
|
@@ -32,8 +32,20 @@ export function clickOutside(node, options) {
|
|
|
32
32
|
}
|
|
33
33
|
};
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
let scrollLocks = 0;
|
|
36
|
+
let previousOverflow = '';
|
|
37
|
+
/** Blocks the scroll of the page; each call needs its own unlockScroll() */
|
|
38
|
+
export function lockScroll() {
|
|
39
|
+
if (typeof document === 'undefined')
|
|
40
|
+
return;
|
|
41
|
+
if (scrollLocks++ === 0) {
|
|
42
|
+
previousOverflow = document.body.style.overflow;
|
|
43
|
+
document.body.style.overflow = 'hidden';
|
|
38
44
|
}
|
|
39
45
|
}
|
|
46
|
+
export function unlockScroll() {
|
|
47
|
+
if (typeof document === 'undefined' || scrollLocks === 0)
|
|
48
|
+
return;
|
|
49
|
+
if (--scrollLocks === 0)
|
|
50
|
+
document.body.style.overflow = previousOverflow;
|
|
51
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "lapikit",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.5",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -80,8 +80,11 @@
|
|
|
80
80
|
"default": "./dist/hooks/actions.js"
|
|
81
81
|
}
|
|
82
82
|
},
|
|
83
|
+
"dependencies": {
|
|
84
|
+
"esm-env": "^1.2.2"
|
|
85
|
+
},
|
|
83
86
|
"peerDependencies": {
|
|
84
|
-
"svelte": "^5.
|
|
87
|
+
"svelte": "^5.20.0"
|
|
85
88
|
},
|
|
86
89
|
"devDependencies": {
|
|
87
90
|
"@eslint/compat": "^1.2.5",
|
|
@@ -106,7 +109,7 @@
|
|
|
106
109
|
"prettier-plugin-svelte": "^3.3.3",
|
|
107
110
|
"publint": "^0.3.2",
|
|
108
111
|
"sass": "^1.105.1",
|
|
109
|
-
"svelte": "^5.
|
|
112
|
+
"svelte": "^5.20.0",
|
|
110
113
|
"svelte-check": "^4.0.0",
|
|
111
114
|
"typescript": "^5.0.0",
|
|
112
115
|
"typescript-eslint": "^8.20.0",
|