@dryui/primitives 0.1.0 → 0.1.4
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/beam/beam.svelte +37 -9
- package/dist/chromatic-aberration/chromatic-aberration.svelte +60 -19
- package/dist/date-field/date-field-root.svelte +71 -21
- package/dist/date-field/date-field-segment.svelte +11 -9
- package/dist/date-field/date-field-separator.svelte +1 -1
- package/dist/image-comparison/image-comparison.svelte +18 -27
- package/dist/rich-text-editor/context.svelte.d.ts +26 -25
- package/dist/rich-text-editor/index.d.ts +2 -1
- package/dist/rich-text-editor/index.js +1 -0
- package/package.json +1 -1
package/dist/beam/beam.svelte
CHANGED
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
angle = 45,
|
|
20
20
|
speed = 3,
|
|
21
21
|
intensity = 70,
|
|
22
|
-
blendMode
|
|
22
|
+
blendMode,
|
|
23
23
|
children,
|
|
24
24
|
class: className,
|
|
25
25
|
style,
|
|
@@ -31,26 +31,33 @@
|
|
|
31
31
|
const gradientString = $derived(
|
|
32
32
|
`linear-gradient(${angle}deg, transparent 0%, transparent calc(50% - ${width}px), ${color} 50%, transparent calc(50% + ${width}px), transparent 100%)`
|
|
33
33
|
);
|
|
34
|
+
const rootStyle = $derived.by(() => {
|
|
35
|
+
const declarations = [
|
|
36
|
+
style,
|
|
37
|
+
`--dry-beam-speed: ${speedValue}`,
|
|
38
|
+
`--dry-beam-intensity: ${clampedIntensity}`,
|
|
39
|
+
`--dry-beam-width: ${width}px`,
|
|
40
|
+
blendMode ? `--dry-beam-blend: ${blendMode}` : null
|
|
41
|
+
].filter(Boolean);
|
|
42
|
+
return declarations.join('; ');
|
|
43
|
+
});
|
|
44
|
+
const layerStyle = $derived(`background: ${gradientString};`);
|
|
34
45
|
|
|
35
46
|
function applyRootStyles(node: HTMLElement) {
|
|
36
47
|
$effect(() => {
|
|
37
|
-
node.style.cssText =
|
|
38
|
-
node.style.setProperty('--dry-beam-speed', speedValue);
|
|
39
|
-
node.style.setProperty('--dry-beam-intensity', clampedIntensity);
|
|
40
|
-
node.style.setProperty('--dry-beam-blend', blendMode);
|
|
41
|
-
node.style.setProperty('--dry-beam-width', `${width}px`);
|
|
48
|
+
node.style.cssText = rootStyle;
|
|
42
49
|
});
|
|
43
50
|
}
|
|
44
51
|
|
|
45
52
|
function applyLayerStyles(node: HTMLElement) {
|
|
46
53
|
$effect(() => {
|
|
47
|
-
node.style.
|
|
54
|
+
node.style.cssText = layerStyle;
|
|
48
55
|
});
|
|
49
56
|
}
|
|
50
57
|
</script>
|
|
51
58
|
|
|
52
|
-
<div class={['beam', className]} {...rest}
|
|
53
|
-
<div class="beam-layer"
|
|
59
|
+
<div class={['beam', className]} {...rest} {@attach applyRootStyles}>
|
|
60
|
+
<div class="beam-layer" {@attach applyLayerStyles}></div>
|
|
54
61
|
{#if children}
|
|
55
62
|
{@render children()}
|
|
56
63
|
{/if}
|
|
@@ -65,5 +72,26 @@
|
|
|
65
72
|
position: absolute;
|
|
66
73
|
inset: 0;
|
|
67
74
|
pointer-events: none;
|
|
75
|
+
background-size: 300% 300%;
|
|
76
|
+
opacity: calc(var(--dry-beam-intensity, 70) / 100);
|
|
77
|
+
mix-blend-mode: var(--dry-beam-blend, var(--dry-beam-default-blend, multiply));
|
|
78
|
+
filter: blur(calc(var(--dry-beam-width, 2px) * 2));
|
|
79
|
+
animation: beam-sweep var(--dry-beam-speed, 3s) ease-in-out infinite;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
@keyframes beam-sweep {
|
|
83
|
+
0% {
|
|
84
|
+
background-position: -50% -50%;
|
|
85
|
+
}
|
|
86
|
+
100% {
|
|
87
|
+
background-position: 150% 150%;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
@media (prefers-reduced-motion: reduce) {
|
|
92
|
+
.beam-layer {
|
|
93
|
+
animation: none;
|
|
94
|
+
background-position: 50% 50%;
|
|
95
|
+
}
|
|
68
96
|
}
|
|
69
97
|
</style>
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { createId } from '../utils/create-id.js';
|
|
4
5
|
|
|
5
6
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
6
7
|
offset?: number;
|
|
@@ -8,61 +9,101 @@
|
|
|
8
9
|
children: Snippet;
|
|
9
10
|
}
|
|
10
11
|
|
|
11
|
-
let instanceCounter = 0;
|
|
12
|
-
|
|
13
12
|
let { offset = 3, angle = 0, children, class: className, style, ...rest }: Props = $props();
|
|
14
13
|
|
|
15
|
-
const filterId =
|
|
14
|
+
const filterId = createId('dry-chromatic');
|
|
16
15
|
|
|
17
16
|
const offsetX = $derived(Math.round(offset * Math.cos((angle * Math.PI) / 180)));
|
|
18
17
|
const offsetY = $derived(Math.round(offset * Math.sin((angle * Math.PI) / 180)));
|
|
19
18
|
|
|
20
19
|
function applyFilterStyles(node: HTMLElement) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
node.style.setProperty('filter', `url(#${filterId})`);
|
|
24
|
-
});
|
|
20
|
+
node.style.cssText = style || '';
|
|
21
|
+
node.style.setProperty('filter', `url(#${filterId})`);
|
|
25
22
|
}
|
|
26
23
|
</script>
|
|
27
24
|
|
|
28
|
-
<svg class="chromatic-aberration-svg" aria-hidden="true">
|
|
25
|
+
<svg class="chromatic-aberration-svg" width="0" height="0" aria-hidden="true">
|
|
29
26
|
<defs>
|
|
30
27
|
<filter id={filterId} color-interpolation-filters="sRGB">
|
|
31
|
-
<feOffset in="SourceGraphic" dx={offsetX} dy={offsetY} result="
|
|
28
|
+
<feOffset in="SourceGraphic" dx={offsetX} dy={offsetY} result="lightRed" />
|
|
32
29
|
<feColorMatrix
|
|
33
|
-
in="
|
|
30
|
+
in="lightRed"
|
|
34
31
|
type="matrix"
|
|
35
32
|
values="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"
|
|
36
|
-
result="
|
|
33
|
+
result="lightRedOnly"
|
|
37
34
|
/>
|
|
38
|
-
<feOffset in="SourceGraphic" dx={-offsetX} dy={-offsetY} result="
|
|
35
|
+
<feOffset in="SourceGraphic" dx={-offsetX} dy={-offsetY} result="lightBlue" />
|
|
39
36
|
<feColorMatrix
|
|
40
|
-
in="
|
|
37
|
+
in="lightBlue"
|
|
41
38
|
type="matrix"
|
|
42
39
|
values="0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0"
|
|
43
|
-
result="
|
|
40
|
+
result="lightBlueOnly"
|
|
41
|
+
/>
|
|
42
|
+
<feColorMatrix
|
|
43
|
+
in="SourceGraphic"
|
|
44
|
+
type="matrix"
|
|
45
|
+
values="0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0"
|
|
46
|
+
result="lightGreenOnly"
|
|
44
47
|
/>
|
|
48
|
+
<feBlend in="lightRedOnly" in2="lightGreenOnly" mode="screen" result="lightRG" />
|
|
49
|
+
<feBlend in="lightRG" in2="lightBlueOnly" mode="screen" result="lightSplit" />
|
|
45
50
|
<feColorMatrix
|
|
46
51
|
in="SourceGraphic"
|
|
47
52
|
type="matrix"
|
|
53
|
+
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
54
|
+
result="darkSource"
|
|
55
|
+
/>
|
|
56
|
+
<feOffset in="darkSource" dx={offsetX} dy={offsetY} result="darkRed" />
|
|
57
|
+
<feColorMatrix
|
|
58
|
+
in="darkRed"
|
|
59
|
+
type="matrix"
|
|
60
|
+
values="1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0"
|
|
61
|
+
result="darkRedOnly"
|
|
62
|
+
/>
|
|
63
|
+
<feOffset in="darkSource" dx={-offsetX} dy={-offsetY} result="darkBlue" />
|
|
64
|
+
<feColorMatrix
|
|
65
|
+
in="darkBlue"
|
|
66
|
+
type="matrix"
|
|
67
|
+
values="0 0 0 0 0 0 0 0 0 0 0 0 1 0 0 0 0 0 1 0"
|
|
68
|
+
result="darkBlueOnly"
|
|
69
|
+
/>
|
|
70
|
+
<feColorMatrix
|
|
71
|
+
in="darkSource"
|
|
72
|
+
type="matrix"
|
|
48
73
|
values="0 0 0 0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 1 0"
|
|
49
|
-
result="
|
|
74
|
+
result="darkGreenOnly"
|
|
75
|
+
/>
|
|
76
|
+
<feBlend in="darkRedOnly" in2="darkGreenOnly" mode="screen" result="darkRG" />
|
|
77
|
+
<feBlend in="darkRG" in2="darkBlueOnly" mode="screen" result="darkSplitInverted" />
|
|
78
|
+
<feColorMatrix
|
|
79
|
+
in="darkSplitInverted"
|
|
80
|
+
type="matrix"
|
|
81
|
+
values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"
|
|
82
|
+
result="darkSplit"
|
|
50
83
|
/>
|
|
51
|
-
<
|
|
52
|
-
<
|
|
84
|
+
<feColorMatrix in="SourceGraphic" type="luminanceToAlpha" result="lightMask" />
|
|
85
|
+
<feComponentTransfer in="lightMask" result="darkMask">
|
|
86
|
+
<feFuncA type="table" tableValues="1 0" />
|
|
87
|
+
</feComponentTransfer>
|
|
88
|
+
<feComposite in="lightSplit" in2="lightMask" operator="in" result="lightApplied" />
|
|
89
|
+
<feComposite in="darkSplit" in2="darkMask" operator="in" result="darkApplied" />
|
|
90
|
+
<feMerge>
|
|
91
|
+
<feMergeNode in="lightApplied" />
|
|
92
|
+
<feMergeNode in="darkApplied" />
|
|
93
|
+
</feMerge>
|
|
53
94
|
</filter>
|
|
54
95
|
</defs>
|
|
55
96
|
</svg>
|
|
56
|
-
<div class={['chromatic-aberration', className]}
|
|
97
|
+
<div class={['chromatic-aberration', className]} {@attach applyFilterStyles} {...rest}>
|
|
57
98
|
{@render children()}
|
|
58
99
|
</div>
|
|
59
100
|
|
|
60
101
|
<style>
|
|
61
102
|
.chromatic-aberration-svg {
|
|
62
103
|
position: absolute;
|
|
63
|
-
width: 0;
|
|
64
104
|
height: 0;
|
|
65
105
|
overflow: hidden;
|
|
106
|
+
pointer-events: none;
|
|
66
107
|
}
|
|
67
108
|
|
|
68
109
|
.chromatic-aberration {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { Snippet } from 'svelte';
|
|
3
3
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
4
|
+
import { SvelteMap } from 'svelte/reactivity';
|
|
4
5
|
import { setDateFieldCtx, getLocaleFormat, type DateSegmentType } from './context.svelte.js';
|
|
5
6
|
|
|
6
7
|
interface Props extends HTMLAttributes<HTMLDivElement> {
|
|
@@ -13,6 +14,12 @@
|
|
|
13
14
|
children: Snippet;
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
interface SegmentValues {
|
|
18
|
+
month: number | null;
|
|
19
|
+
day: number | null;
|
|
20
|
+
year: number | null;
|
|
21
|
+
}
|
|
22
|
+
|
|
16
23
|
let {
|
|
17
24
|
value = $bindable<Date | null>(null),
|
|
18
25
|
name,
|
|
@@ -24,37 +31,61 @@
|
|
|
24
31
|
...rest
|
|
25
32
|
}: Props = $props();
|
|
26
33
|
|
|
27
|
-
let
|
|
28
|
-
let day = $state<number | null>(value ? value.getDate() : null);
|
|
29
|
-
let year = $state<number | null>(value ? value.getFullYear() : null);
|
|
34
|
+
let draftValues = $state<SegmentValues | null>(null);
|
|
30
35
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
month = value.getMonth() + 1;
|
|
35
|
-
day = value.getDate();
|
|
36
|
-
year = value.getFullYear();
|
|
36
|
+
function getSegmentValues(date: Date | null): SegmentValues {
|
|
37
|
+
if (!date) {
|
|
38
|
+
return { month: null, day: null, year: null };
|
|
37
39
|
}
|
|
38
|
-
});
|
|
39
40
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
return {
|
|
42
|
+
month: date.getMonth() + 1,
|
|
43
|
+
day: date.getDate(),
|
|
44
|
+
year: date.getFullYear()
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function commitSegments(nextValues: SegmentValues) {
|
|
49
|
+
if (
|
|
50
|
+
nextValues.month !== null &&
|
|
51
|
+
nextValues.day !== null &&
|
|
52
|
+
nextValues.year !== null &&
|
|
53
|
+
nextValues.year >= 1000
|
|
54
|
+
) {
|
|
55
|
+
const d = new Date(nextValues.year, nextValues.month - 1, nextValues.day);
|
|
56
|
+
if (d.getMonth() === nextValues.month - 1 && d.getDate() === nextValues.day) {
|
|
44
57
|
value = d;
|
|
58
|
+
draftValues = null;
|
|
59
|
+
return;
|
|
45
60
|
}
|
|
46
61
|
}
|
|
62
|
+
|
|
63
|
+
draftValues = nextValues;
|
|
47
64
|
}
|
|
48
65
|
|
|
49
66
|
const localeFormat = $derived(getLocaleFormat(locale));
|
|
67
|
+
const committedValues = $derived(getSegmentValues(value));
|
|
68
|
+
const activeValues = $derived(draftValues ?? committedValues);
|
|
50
69
|
|
|
51
70
|
const segments = $derived(
|
|
52
71
|
localeFormat.order.map((type) => ({
|
|
53
72
|
type,
|
|
54
|
-
value:
|
|
73
|
+
value:
|
|
74
|
+
type === 'month'
|
|
75
|
+
? activeValues.month
|
|
76
|
+
: type === 'day'
|
|
77
|
+
? activeValues.day
|
|
78
|
+
: activeValues.year
|
|
55
79
|
}))
|
|
56
80
|
);
|
|
57
81
|
|
|
82
|
+
function focusPreferredSegment() {
|
|
83
|
+
const targetType =
|
|
84
|
+
segments.find((segment) => segment.value === null)?.type ?? localeFormat.order[0];
|
|
85
|
+
if (!targetType) return;
|
|
86
|
+
segmentElements.get(targetType)?.focus();
|
|
87
|
+
}
|
|
88
|
+
|
|
58
89
|
function serializeDateValue(date: Date | null): string {
|
|
59
90
|
if (!date) return '';
|
|
60
91
|
|
|
@@ -66,7 +97,7 @@
|
|
|
66
97
|
}
|
|
67
98
|
|
|
68
99
|
// Segment element registry for index-based navigation
|
|
69
|
-
const segmentElements = new
|
|
100
|
+
const segmentElements = new SvelteMap<DateSegmentType, HTMLElement>();
|
|
70
101
|
|
|
71
102
|
setDateFieldCtx({
|
|
72
103
|
get value() {
|
|
@@ -94,10 +125,11 @@
|
|
|
94
125
|
return segments;
|
|
95
126
|
},
|
|
96
127
|
updateSegment(type: DateSegmentType, val: number) {
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
128
|
+
commitSegments({
|
|
129
|
+
month: type === 'month' ? val : activeValues.month,
|
|
130
|
+
day: type === 'day' ? val : activeValues.day,
|
|
131
|
+
year: type === 'year' ? val : activeValues.year
|
|
132
|
+
});
|
|
101
133
|
},
|
|
102
134
|
registerSegment(type: DateSegmentType, el: HTMLElement) {
|
|
103
135
|
segmentElements.set(type, el);
|
|
@@ -116,9 +148,27 @@
|
|
|
116
148
|
}
|
|
117
149
|
}
|
|
118
150
|
});
|
|
151
|
+
|
|
152
|
+
function handleMousedown(event: MouseEvent) {
|
|
153
|
+
if (disabled) return;
|
|
154
|
+
const target = event.target;
|
|
155
|
+
if (!(target instanceof HTMLElement)) return;
|
|
156
|
+
if (target.closest('[data-df-segment]')) return;
|
|
157
|
+
|
|
158
|
+
event.preventDefault();
|
|
159
|
+
focusPreferredSegment();
|
|
160
|
+
}
|
|
119
161
|
</script>
|
|
120
162
|
|
|
121
|
-
<div
|
|
163
|
+
<div
|
|
164
|
+
role="group"
|
|
165
|
+
aria-label="Date"
|
|
166
|
+
data-df-wrapper
|
|
167
|
+
data-df-root
|
|
168
|
+
data-disabled={disabled || undefined}
|
|
169
|
+
onmousedown={handleMousedown}
|
|
170
|
+
{...rest}
|
|
171
|
+
>
|
|
122
172
|
{@render children()}
|
|
123
173
|
|
|
124
174
|
{#if name}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
<script lang="ts">
|
|
2
2
|
import type { HTMLAttributes } from 'svelte/elements';
|
|
3
3
|
import { getDateFieldCtx, type DateSegmentType } from './context.svelte.js';
|
|
4
|
-
import { onMount } from 'svelte';
|
|
5
4
|
|
|
6
5
|
interface Props extends HTMLAttributes<HTMLSpanElement> {
|
|
7
6
|
type: DateSegmentType;
|
|
@@ -11,13 +10,6 @@
|
|
|
11
10
|
|
|
12
11
|
const ctx = getDateFieldCtx();
|
|
13
12
|
|
|
14
|
-
let el: HTMLSpanElement;
|
|
15
|
-
|
|
16
|
-
onMount(() => {
|
|
17
|
-
ctx.registerSegment(type, el);
|
|
18
|
-
return () => ctx.unregisterSegment(type);
|
|
19
|
-
});
|
|
20
|
-
|
|
21
13
|
const segmentData = $derived(ctx.segments.find((s) => s.type === type));
|
|
22
14
|
|
|
23
15
|
const minValue = $derived(type === 'month' ? 1 : type === 'day' ? 1 : 1000);
|
|
@@ -35,6 +27,15 @@
|
|
|
35
27
|
let inputBuffer = '';
|
|
36
28
|
let bufferTimeout: ReturnType<typeof setTimeout>;
|
|
37
29
|
|
|
30
|
+
function registerSegment(node: HTMLSpanElement) {
|
|
31
|
+
ctx.registerSegment(type, node);
|
|
32
|
+
return {
|
|
33
|
+
destroy() {
|
|
34
|
+
ctx.unregisterSegment(type);
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
|
|
38
39
|
function increment() {
|
|
39
40
|
const current = segmentData?.value ?? minValue - 1;
|
|
40
41
|
const next = current >= maxValue ? minValue : current + 1;
|
|
@@ -111,7 +112,7 @@
|
|
|
111
112
|
</script>
|
|
112
113
|
|
|
113
114
|
<span
|
|
114
|
-
|
|
115
|
+
{@attach registerSegment}
|
|
115
116
|
role="spinbutton"
|
|
116
117
|
tabindex={ctx.disabled ? undefined : 0}
|
|
117
118
|
aria-label={type}
|
|
@@ -119,6 +120,7 @@
|
|
|
119
120
|
aria-valuemax={maxValue}
|
|
120
121
|
aria-valuenow={segmentData?.value ?? undefined}
|
|
121
122
|
aria-valuetext={displayValue}
|
|
123
|
+
data-df-segment
|
|
122
124
|
data-segment={type}
|
|
123
125
|
data-placeholder={segmentData?.value === null ? '' : undefined}
|
|
124
126
|
data-disabled={ctx.disabled || undefined}
|
|
@@ -21,20 +21,15 @@
|
|
|
21
21
|
...rest
|
|
22
22
|
}: Props = $props();
|
|
23
23
|
|
|
24
|
-
let containerEl = $state<HTMLDivElement>();
|
|
25
24
|
let dragging = $state(false);
|
|
26
25
|
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
if (containerEl === node) containerEl = undefined;
|
|
32
|
-
}
|
|
33
|
-
};
|
|
26
|
+
function syncStyles(node: HTMLElement) {
|
|
27
|
+
$effect(() => {
|
|
28
|
+
node.style.cssText = `${style ? `${style}; ` : ''}--dry-image-comparison-position: ${position}%`;
|
|
29
|
+
});
|
|
34
30
|
}
|
|
35
31
|
|
|
36
|
-
function updatePosition(clientX: number, clientY: number) {
|
|
37
|
-
if (!containerEl) return;
|
|
32
|
+
function updatePosition(clientX: number, clientY: number, containerEl: HTMLElement) {
|
|
38
33
|
const rect = containerEl.getBoundingClientRect();
|
|
39
34
|
let pct: number;
|
|
40
35
|
if (orientation === 'horizontal') {
|
|
@@ -47,13 +42,16 @@
|
|
|
47
42
|
|
|
48
43
|
function onPointerDown(e: PointerEvent) {
|
|
49
44
|
dragging = true;
|
|
50
|
-
|
|
51
|
-
|
|
45
|
+
const handleEl = e.currentTarget as HTMLElement;
|
|
46
|
+
handleEl.setPointerCapture(e.pointerId);
|
|
47
|
+
const containerEl = handleEl.closest<HTMLElement>('.root');
|
|
48
|
+
if (!containerEl) return;
|
|
49
|
+
updatePosition(e.clientX, e.clientY, containerEl);
|
|
52
50
|
}
|
|
53
51
|
|
|
54
52
|
function onPointerMove(e: PointerEvent) {
|
|
55
53
|
if (!dragging) return;
|
|
56
|
-
updatePosition(e.clientX, e.clientY);
|
|
54
|
+
updatePosition(e.clientX, e.clientY, e.currentTarget as HTMLElement);
|
|
57
55
|
}
|
|
58
56
|
|
|
59
57
|
function onPointerUp() {
|
|
@@ -70,24 +68,16 @@
|
|
|
70
68
|
position = Math.min(position + step, 100);
|
|
71
69
|
}
|
|
72
70
|
}
|
|
73
|
-
|
|
74
|
-
function applyStyles(node: HTMLElement) {
|
|
75
|
-
$effect(() => {
|
|
76
|
-
node.style.cssText = style || '';
|
|
77
|
-
node.style.setProperty('--dry-image-comparison-position', `${position}%`);
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
71
|
</script>
|
|
81
72
|
|
|
82
73
|
<div
|
|
83
|
-
{@attach
|
|
74
|
+
{@attach syncStyles}
|
|
84
75
|
data-orientation={orientation}
|
|
85
76
|
data-dragging={dragging || undefined}
|
|
86
77
|
class={['root', className]}
|
|
87
78
|
onpointermove={onPointerMove}
|
|
88
79
|
onpointerup={onPointerUp}
|
|
89
80
|
{...rest}
|
|
90
|
-
use:applyStyles
|
|
91
81
|
>
|
|
92
82
|
<div data-part="after" class="layer">
|
|
93
83
|
{@render after()}
|
|
@@ -119,6 +109,8 @@
|
|
|
119
109
|
.root {
|
|
120
110
|
--dry-image-comparison-handle-z-index: 1;
|
|
121
111
|
position: relative;
|
|
112
|
+
display: grid;
|
|
113
|
+
height: 100%;
|
|
122
114
|
overflow: hidden;
|
|
123
115
|
touch-action: none;
|
|
124
116
|
user-select: none;
|
|
@@ -130,8 +122,8 @@
|
|
|
130
122
|
}
|
|
131
123
|
|
|
132
124
|
.layer {
|
|
133
|
-
|
|
134
|
-
|
|
125
|
+
grid-area: 1 / 1;
|
|
126
|
+
min-height: 0;
|
|
135
127
|
}
|
|
136
128
|
|
|
137
129
|
.root[data-orientation='horizontal'] .before {
|
|
@@ -144,9 +136,8 @@
|
|
|
144
136
|
|
|
145
137
|
.handle {
|
|
146
138
|
position: absolute;
|
|
147
|
-
display:
|
|
148
|
-
|
|
149
|
-
justify-content: center;
|
|
139
|
+
display: grid;
|
|
140
|
+
place-items: center;
|
|
150
141
|
z-index: var(--dry-image-comparison-handle-z-index);
|
|
151
142
|
}
|
|
152
143
|
|
|
@@ -1,27 +1,28 @@
|
|
|
1
1
|
export interface RichTextEditorContext {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
2
|
+
readonly isBold: boolean;
|
|
3
|
+
readonly isItalic: boolean;
|
|
4
|
+
readonly isUnderline: boolean;
|
|
5
|
+
readonly isStrikethrough: boolean;
|
|
6
|
+
readonly isOrderedList: boolean;
|
|
7
|
+
readonly isUnorderedList: boolean;
|
|
8
|
+
readonly currentHeading: string | null;
|
|
9
|
+
readonly currentLink: string | null;
|
|
10
|
+
readonly html: string;
|
|
11
|
+
readonly readonly: boolean;
|
|
12
|
+
readonly placeholder: string;
|
|
13
|
+
contentEl: HTMLDivElement | null;
|
|
14
|
+
execCommand: (command: string, value?: string) => void;
|
|
15
|
+
toggleBold: () => void;
|
|
16
|
+
toggleItalic: () => void;
|
|
17
|
+
toggleUnderline: () => void;
|
|
18
|
+
toggleStrikethrough: () => void;
|
|
19
|
+
toggleOrderedList: () => void;
|
|
20
|
+
toggleUnorderedList: () => void;
|
|
21
|
+
setHeading: (level: 'h1' | 'h2' | 'h3' | 'p') => void;
|
|
22
|
+
insertLink: (url: string) => void;
|
|
23
|
+
removeLink: () => void;
|
|
24
|
+
getContent: () => string;
|
|
25
|
+
updateState: () => void;
|
|
26
|
+
syncValue: () => void;
|
|
25
27
|
}
|
|
26
|
-
export declare
|
|
27
|
-
export declare function getRichTextEditorCtx(): RichTextEditorContext;
|
|
28
|
+
export declare const setRichTextEditorCtx: (ctx: RichTextEditorContext) => RichTextEditorContext, getRichTextEditorCtx: () => RichTextEditorContext;
|
|
@@ -30,6 +30,8 @@ export interface RichTextEditorToolbarProps extends Omit<HTMLAttributes<HTMLDivE
|
|
|
30
30
|
}
|
|
31
31
|
export interface RichTextEditorContentProps extends HTMLAttributes<HTMLDivElement> {
|
|
32
32
|
}
|
|
33
|
+
export { setRichTextEditorCtx, getRichTextEditorCtx } from './context.svelte.js';
|
|
34
|
+
export type { RichTextEditorContext } from './context.svelte.js';
|
|
33
35
|
import RichTextEditorRoot from './rich-text-editor-root.svelte';
|
|
34
36
|
import RichTextEditorToolbar from './rich-text-editor-toolbar.svelte';
|
|
35
37
|
import RichTextEditorContent from './rich-text-editor-content.svelte';
|
|
@@ -38,4 +40,3 @@ export declare const RichTextEditor: {
|
|
|
38
40
|
Toolbar: typeof RichTextEditorToolbar;
|
|
39
41
|
Content: typeof RichTextEditorContent;
|
|
40
42
|
};
|
|
41
|
-
export {};
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { setRichTextEditorCtx, getRichTextEditorCtx } from './context.svelte.js';
|
|
1
2
|
import RichTextEditorRoot from './rich-text-editor-root.svelte';
|
|
2
3
|
import RichTextEditorToolbar from './rich-text-editor-toolbar.svelte';
|
|
3
4
|
import RichTextEditorContent from './rich-text-editor-content.svelte';
|