plass-ui 1.0.0 → 1.0.2
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 +165 -0
- package/dist/components/accordion/PlAccordion.js +1 -131
- package/dist/components/accordion/index.js +1 -1
- package/dist/components/alert/PlAlert.js +1 -109
- package/dist/components/alert/index.js +1 -1
- package/dist/components/animate-appear/PlAnimateAppear.js +1 -71
- package/dist/components/animate-appear/index.js +1 -1
- package/dist/components/animate-blink/PlAnimateBlink.js +1 -47
- package/dist/components/animate-blink/index.js +1 -1
- package/dist/components/animate-fade/PlAnimateFade.js +1 -48
- package/dist/components/animate-fade/index.js +1 -1
- package/dist/components/animate-grow/PlAnimateGrow.js +1 -49
- package/dist/components/animate-grow/index.js +1 -1
- package/dist/components/animate-headline/PlAnimateHeadline.js +1 -120
- package/dist/components/animate-headline/index.js +1 -1
- package/dist/components/animate-lighting/PlAnimateLighting.js +1 -65
- package/dist/components/animate-lighting/index.js +1 -1
- package/dist/components/animate-marquee/PlAnimateMarquee.js +1 -94
- package/dist/components/animate-marquee/index.js +1 -1
- package/dist/components/animate-rotate/PlAnimateRotate.js +1 -50
- package/dist/components/animate-rotate/index.js +1 -1
- package/dist/components/animate-slide/PlAnimateSlide.js +1 -49
- package/dist/components/animate-slide/index.js +1 -1
- package/dist/components/animate-typing/PlAnimateTyping.js +1 -177
- package/dist/components/animate-typing/index.js +1 -1
- package/dist/components/animate-zoom/PlAnimateZoom.js +1 -45
- package/dist/components/animate-zoom/index.js +1 -1
- package/dist/components/aspect-ratio/PlAspectRatio.js +1 -58
- package/dist/components/aspect-ratio/index.js +1 -1
- package/dist/components/avatar/PlAvatar.js +1 -121
- package/dist/components/avatar/index.js +1 -1
- package/dist/components/badge/PlBadge.js +1 -168
- package/dist/components/badge/index.js +1 -1
- package/dist/components/blockquote/PlBlockquote.js +1 -112
- package/dist/components/blockquote/index.js +1 -1
- package/dist/components/bottom-navigation/PlBottomNavigation.js +1 -141
- package/dist/components/bottom-navigation/index.js +1 -1
- package/dist/components/box/PlBox.js +1 -46
- package/dist/components/box/index.js +1 -1
- package/dist/components/breadcrumb/PlBreadcrumb.js +1 -201
- package/dist/components/breadcrumb/index.js +1 -1
- package/dist/components/button/PlButton.js +1 -196
- package/dist/components/button/index.js +1 -1
- package/dist/components/button-group/PlButtonGroup.js +1 -64
- package/dist/components/button-group/index.js +1 -1
- package/dist/components/card/PlCard.js +1 -102
- package/dist/components/card/index.js +1 -1
- package/dist/components/carousel/PlCarousel.js +1 -177
- package/dist/components/carousel/index.js +1 -1
- package/dist/components/chat-bubble/PlChatBubble.js +1 -206
- package/dist/components/chat-bubble/index.js +1 -1
- package/dist/components/checkbox/PlCheckbox.js +1 -100
- package/dist/components/checkbox/index.js +1 -1
- package/dist/components/chip/PlChip.js +1 -144
- package/dist/components/chip/index.js +1 -1
- package/dist/components/collapsible/PlCollapsible.js +1 -65
- package/dist/components/collapsible/index.js +1 -1
- package/dist/components/combobox/PlCombobox.js +1 -199
- package/dist/components/combobox/index.js +1 -1
- package/dist/components/container/PlContainer.js +1 -47
- package/dist/components/container/index.js +1 -1
- package/dist/components/date-picker/PlDatePicker.js +1 -87
- package/dist/components/date-picker/index.js +1 -1
- package/dist/components/date-range-picker/PlDateRangePicker.js +1 -152
- package/dist/components/date-range-picker/index.js +1 -1
- package/dist/components/date-time-picker/PlDateTimePicker.js +1 -106
- package/dist/components/date-time-picker/index.js +1 -1
- package/dist/components/divider/PlDivider.js +1 -107
- package/dist/components/divider/index.js +1 -1
- package/dist/components/drawer/PlDrawer.js +1 -190
- package/dist/components/drawer/index.js +1 -1
- package/dist/components/file-picker/PlFilePicker.js +1 -274
- package/dist/components/file-picker/index.js +1 -1
- package/dist/components/floating-bottom-navigation/PlFloatingBottomNavigation.js +1 -291
- package/dist/components/floating-bottom-navigation/index.js +1 -1
- package/dist/components/grid/PlGrid.js +1 -51
- package/dist/components/grid/PlGridItem.js +1 -34
- package/dist/components/grid/index.js +1 -2
- package/dist/components/highlight/PlHighlight.js +1 -185
- package/dist/components/highlight/index.js +1 -1
- package/dist/components/hot-keys/PlHotKeys.js +1 -294
- package/dist/components/hot-keys/index.js +1 -1
- package/dist/components/icon/PlIcon.js +1 -58
- package/dist/components/icon/index.js +1 -1
- package/dist/components/icon-button/PlIconButton.js +1 -37
- package/dist/components/icon-button/index.js +1 -1
- package/dist/components/list/PlList.js +1 -160
- package/dist/components/list/index.js +1 -1
- package/dist/components/menu/PlMenu.js +1 -209
- package/dist/components/menu/index.js +1 -1
- package/dist/components/modal/PlModal.js +1 -150
- package/dist/components/modal/index.js +1 -1
- package/dist/components/number-field/PlNumberField.js +1 -111
- package/dist/components/number-field/index.js +1 -1
- package/dist/components/otp-field/PlOtpField.js +1 -109
- package/dist/components/otp-field/index.js +1 -1
- package/dist/components/overlay/PlOverlay.js +1 -77
- package/dist/components/overlay/index.js +1 -1
- package/dist/components/pagination/PlPagination.js +1 -159
- package/dist/components/pagination/index.js +1 -1
- package/dist/components/panes/PlPanes.js +1 -324
- package/dist/components/panes/index.js +1 -1
- package/dist/components/pill/PlPill.js +1 -154
- package/dist/components/pill/index.js +1 -1
- package/dist/components/popover/PlPopover.js +1 -113
- package/dist/components/popover/index.js +1 -1
- package/dist/components/progress-box/PlProgressBox.js +1 -34
- package/dist/components/progress-box/index.js +1 -1
- package/dist/components/progress-circular/PlProgressCircular.js +1 -47
- package/dist/components/progress-circular/index.js +1 -1
- package/dist/components/progress-linear/PlProgressLinear.js +1 -40
- package/dist/components/progress-linear/index.js +1 -1
- package/dist/components/radio-group/PlRadioGroup.js +1 -99
- package/dist/components/radio-group/index.js +1 -1
- package/dist/components/rating/PlRating.js +1 -101
- package/dist/components/rating/index.js +1 -1
- package/dist/components/scroll-zone/PlScrollZone.js +1 -411
- package/dist/components/scroll-zone/index.js +1 -1
- package/dist/components/segmented-button/PlSegmentedButton.js +1 -206
- package/dist/components/segmented-button/index.js +1 -1
- package/dist/components/select/PlSelect.js +1 -115
- package/dist/components/select/index.js +1 -1
- package/dist/components/skeleton/PlSkeleton.js +1 -142
- package/dist/components/skeleton/index.js +1 -1
- package/dist/components/slider/PlSlider.js +1 -132
- package/dist/components/slider/index.js +1 -1
- package/dist/components/spoiler/PlSpoiler.js +1 -74
- package/dist/components/spoiler/index.js +1 -1
- package/dist/components/switch/PlSwitch.js +1 -131
- package/dist/components/switch/index.js +1 -1
- package/dist/components/table/PlTable.js +1 -210
- package/dist/components/table/index.js +1 -1
- package/dist/components/tabs/PlTabs.js +1 -182
- package/dist/components/tabs/index.js +1 -1
- package/dist/components/text-field/PlTextField.js +1 -126
- package/dist/components/text-field/index.js +1 -1
- package/dist/components/text-link/PlTextLink.js +1 -136
- package/dist/components/text-link/index.js +1 -1
- package/dist/components/time-picker/PlTimePicker.js +1 -97
- package/dist/components/time-picker/index.js +1 -1
- package/dist/components/timeline/PlTimeline.js +1 -207
- package/dist/components/timeline/index.js +1 -1
- package/dist/components/toast/PlToast.js +1 -174
- package/dist/components/toast/index.js +1 -1
- package/dist/components/toolbar/PlToolbar.js +1 -65
- package/dist/components/toolbar/index.js +1 -1
- package/dist/components/tooltip/PlTooltip.js +1 -117
- package/dist/components/tooltip/index.js +1 -1
- package/dist/components/typography/PlTypography.js +1 -143
- package/dist/components/typography/index.js +1 -1
- package/dist/index.js +1 -75
- package/dist/internal/animate.js +1 -318
- package/dist/internal/button-group.js +2 -19
- package/dist/internal/calendar.js +1 -501
- package/dist/internal/date.js +1 -353
- package/dist/internal/format.js +1 -41
- package/dist/internal/grid.js +1 -143
- package/dist/internal/icons.js +1 -138
- package/dist/internal/menu.js +1 -18
- package/dist/internal/picker.js +1 -139
- package/dist/internal/progress.js +1 -167
- package/dist/internal/sizer.js +1 -35
- package/dist/internal/styles.js +1 -636
- package/dist/types.js +0 -8
- package/package.json +5 -3
package/dist/internal/animate.js
CHANGED
|
@@ -1,318 +1 @@
|
|
|
1
|
-
|
|
2
|
-
* The machinery every `PlAnimate*` component runs on.
|
|
3
|
-
*
|
|
4
|
-
* It lives in `internal/` for the reason `button-group.ts` and `progress.ts`
|
|
5
|
-
* do: eleven components need it and none of them should have to import another.
|
|
6
|
-
*
|
|
7
|
-
* ## The shape of it
|
|
8
|
-
*
|
|
9
|
-
* Every effect is one `@keyframes` in `styles.css` running from a state written
|
|
10
|
-
* entirely in custom properties to the element's natural one. Nothing here
|
|
11
|
-
* generates CSS — it fills `--p-anim-*` slots and the stylesheet decides what
|
|
12
|
-
* they mean, which is the same split `controlSlots()` makes for colour and for
|
|
13
|
-
* the same reason: Tailwind only ever sees class names that appear literally in
|
|
14
|
-
* the source, so a class per duration would not survive the first prop.
|
|
15
|
-
*
|
|
16
|
-
* Because the from-state is the *keyframe* rather than a second class, running
|
|
17
|
-
* an effect backwards is `animation-direction: reverse` and nothing else. That
|
|
18
|
-
* is what makes `mode="out"` free on the five that offer it.
|
|
19
|
-
*
|
|
20
|
-
* ## Where the design language draws the line
|
|
21
|
-
*
|
|
22
|
-
* A Plass **control** never moves — a key that scales resamples its label, and
|
|
23
|
-
* that rule holds without exception. What moves here is content a caller has
|
|
24
|
-
* asked to have moved, and it moves on the independent `translate`, `scale` and
|
|
25
|
-
* `rotate` properties rather than on the `transform` shorthand, so a caller's
|
|
26
|
-
* own transform on the same element survives.
|
|
27
|
-
*
|
|
28
|
-
* ## What is deliberately not here
|
|
29
|
-
*
|
|
30
|
-
* An effect that has to know what its children *are* — a marquee that lays them
|
|
31
|
-
* down twice, a headline that swaps between them, a typewriter that counts
|
|
32
|
-
* graphemes — cannot be a class name and a few numbers. Those are components,
|
|
33
|
-
* and their logic stays in their own files.
|
|
34
|
-
*/
|
|
35
|
-
import * as React from 'react';
|
|
36
|
-
/* ---------------------------------------------------------------------------
|
|
37
|
-
* Slots
|
|
38
|
-
* ------------------------------------------------------------------------- */
|
|
39
|
-
/**
|
|
40
|
-
* Which keyframe an effect runs.
|
|
41
|
-
*
|
|
42
|
-
* `grow` and `zoom` share one: they are the same arithmetic at two strengths,
|
|
43
|
-
* and a second identical `@keyframes` would only be a second place to fix a
|
|
44
|
-
* bug. What separates them is their defaults and their origin, and an origin is
|
|
45
|
-
* a property rather than a keyframe.
|
|
46
|
-
*/
|
|
47
|
-
export const animationClasses = {
|
|
48
|
-
fade: 'plass-anim-fade',
|
|
49
|
-
grow: 'plass-anim-scale',
|
|
50
|
-
slide: 'plass-anim-slide',
|
|
51
|
-
zoom: 'plass-anim-scale',
|
|
52
|
-
rotate: 'plass-anim-rotate',
|
|
53
|
-
blink: 'plass-anim-blink'
|
|
54
|
-
};
|
|
55
|
-
/** The class that reads the slots. Always paired with one of the above. */
|
|
56
|
-
export const animBaseClass = 'plass-anim';
|
|
57
|
-
/** A number is pixels; a string is already a CSS length. */
|
|
58
|
-
export function lengthValue(value) {
|
|
59
|
-
return typeof value === 'number' ? `${value}px` : value;
|
|
60
|
-
}
|
|
61
|
-
/** `'infinite'` reaches CSS as the word; a count reaches it as the number. */
|
|
62
|
-
export function repeatValue(repeat) {
|
|
63
|
-
return repeat === 'infinite' ? 'infinite' : String(repeat);
|
|
64
|
-
}
|
|
65
|
-
export function isInfinite(repeat) {
|
|
66
|
-
return repeat === 'infinite';
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* `normal`, `reverse`, `alternate`, `alternate-reverse` — the four CSS already
|
|
70
|
-
* has, assembled from the two props that mean something to a caller.
|
|
71
|
-
*
|
|
72
|
-
* `mode="out"` is a reversed run rather than a keyframe of its own, which is
|
|
73
|
-
* also why a reversed animation ends held on its own first frame: `fill-mode`
|
|
74
|
-
* is `both`, so a faded-out element stays faded out instead of snapping back.
|
|
75
|
-
*/
|
|
76
|
-
export function directionValue(mode, alternate) {
|
|
77
|
-
if (mode === 'out') {
|
|
78
|
-
return alternate ? 'alternate-reverse' : 'reverse';
|
|
79
|
-
}
|
|
80
|
-
return alternate ? 'alternate' : 'normal';
|
|
81
|
-
}
|
|
82
|
-
/**
|
|
83
|
-
* The `--p-anim-*` slots, as an inline style object.
|
|
84
|
-
*
|
|
85
|
-
* Inline rather than utilities for the reason the colour slots are: these are
|
|
86
|
-
* per-instance numbers, and Tailwind cannot generate a class for a duration it
|
|
87
|
-
* has never seen written down.
|
|
88
|
-
*/
|
|
89
|
-
export function animationSlots(options) {
|
|
90
|
-
const slots = {
|
|
91
|
-
'--p-anim-duration': `${options.duration}ms`,
|
|
92
|
-
'--p-anim-delay': `${options.delay}ms`,
|
|
93
|
-
'--p-anim-repeat': repeatValue(options.repeat),
|
|
94
|
-
'--p-anim-direction': directionValue(options.mode ?? 'in', options.alternate)
|
|
95
|
-
};
|
|
96
|
-
if (options.easing) {
|
|
97
|
-
slots['--p-anim-ease'] = options.easing;
|
|
98
|
-
}
|
|
99
|
-
if (options.opacity !== undefined) {
|
|
100
|
-
slots['--p-anim-opacity'] = String(options.opacity);
|
|
101
|
-
}
|
|
102
|
-
if (options.scale !== undefined) {
|
|
103
|
-
slots['--p-anim-scale'] = String(options.scale);
|
|
104
|
-
}
|
|
105
|
-
if (options.x !== undefined) {
|
|
106
|
-
slots['--p-anim-x'] = options.x;
|
|
107
|
-
}
|
|
108
|
-
if (options.y !== undefined) {
|
|
109
|
-
slots['--p-anim-y'] = options.y;
|
|
110
|
-
}
|
|
111
|
-
if (options.angle !== undefined) {
|
|
112
|
-
slots['--p-anim-angle'] = options.angle;
|
|
113
|
-
}
|
|
114
|
-
if (options.angleTo !== undefined) {
|
|
115
|
-
slots['--p-anim-angle-to'] = options.angleTo;
|
|
116
|
-
}
|
|
117
|
-
return slots;
|
|
118
|
-
}
|
|
119
|
-
/**
|
|
120
|
-
* Which way a slide starts, given the edge it comes from.
|
|
121
|
-
*
|
|
122
|
-
* `PlassSide` is physical everywhere in the library and it stays physical here:
|
|
123
|
-
* something arriving from the top of the window arrives from the top in every
|
|
124
|
-
* writing direction.
|
|
125
|
-
*/
|
|
126
|
-
export function slideOffsets(from, distance) {
|
|
127
|
-
const length = lengthValue(distance);
|
|
128
|
-
const negative = typeof distance === 'number' ? `${-distance}px` : `calc(-1 * ${length})`;
|
|
129
|
-
switch (from) {
|
|
130
|
-
case 'top':
|
|
131
|
-
return { x: '0px', y: negative };
|
|
132
|
-
case 'bottom':
|
|
133
|
-
return { x: '0px', y: length };
|
|
134
|
-
case 'left':
|
|
135
|
-
return { x: negative, y: '0px' };
|
|
136
|
-
default:
|
|
137
|
-
return { x: length, y: '0px' };
|
|
138
|
-
}
|
|
139
|
-
}
|
|
140
|
-
/* ---------------------------------------------------------------------------
|
|
141
|
-
* Running one
|
|
142
|
-
* ------------------------------------------------------------------------- */
|
|
143
|
-
/**
|
|
144
|
-
* Whether the reader has asked for less motion.
|
|
145
|
-
*
|
|
146
|
-
* The CSS side of this is handled in the stylesheet, where every keyframe is
|
|
147
|
-
* switched off at once. This is for the effects whose motion is written in
|
|
148
|
-
* JavaScript — a typewriter, a headline reel — where there is no rule to switch
|
|
149
|
-
* off and the component has to decide for itself what "still" means.
|
|
150
|
-
*
|
|
151
|
-
* `useSyncExternalStore` rather than state plus an effect: a media query is an
|
|
152
|
-
* external store, and reading it in an effect means every animated element on
|
|
153
|
-
* the page renders once with the wrong answer and then again with the right
|
|
154
|
-
* one. Here that first render is the one that would start a typewriter a reader
|
|
155
|
-
* asked not to see.
|
|
156
|
-
*/
|
|
157
|
-
const reducedMotionQuery = '(prefers-reduced-motion: reduce)';
|
|
158
|
-
function subscribeToMotion(onChange) {
|
|
159
|
-
if (typeof window === 'undefined' || !window.matchMedia) {
|
|
160
|
-
return () => { };
|
|
161
|
-
}
|
|
162
|
-
const query = window.matchMedia(reducedMotionQuery);
|
|
163
|
-
query.addEventListener('change', onChange);
|
|
164
|
-
return () => query.removeEventListener('change', onChange);
|
|
165
|
-
}
|
|
166
|
-
function readMotion() {
|
|
167
|
-
return typeof window !== 'undefined' && window.matchMedia
|
|
168
|
-
? window.matchMedia(reducedMotionQuery).matches
|
|
169
|
-
: false;
|
|
170
|
-
}
|
|
171
|
-
/** A server has no reader and so no preference. */
|
|
172
|
-
function motionOnServer() {
|
|
173
|
-
return false;
|
|
174
|
-
}
|
|
175
|
-
export function usePrefersReducedMotion() {
|
|
176
|
-
return React.useSyncExternalStore(subscribeToMotion, readMotion, motionOnServer);
|
|
177
|
-
}
|
|
178
|
-
/**
|
|
179
|
-
* Starts, restarts and holds an animation.
|
|
180
|
-
*
|
|
181
|
-
* Two things here are less obvious than they look.
|
|
182
|
-
*
|
|
183
|
-
* **Waiting is `animation-play-state: paused`, not a second class.** An element
|
|
184
|
-
* that has not been triggered yet has to already look like its own first frame,
|
|
185
|
-
* or a `visible` fade would be fully drawn until it scrolled into view and then
|
|
186
|
-
* blink out to start. With `fill-mode: both` a paused animation shows exactly
|
|
187
|
-
* that frame, so waiting and running are one animation in two states rather
|
|
188
|
-
* than two states to keep in step.
|
|
189
|
-
*
|
|
190
|
-
* **Restarting reaches for the DOM.** There is no way to rewind a CSS animation
|
|
191
|
-
* from React: re-rendering with the same class changes nothing, and a `key`
|
|
192
|
-
* would restart the animation by unmounting the children, taking their state
|
|
193
|
-
* with it. Clearing `animation-name`, reading a layout property to force the
|
|
194
|
-
* style to settle, and putting it back is the one move that rewinds the element
|
|
195
|
-
* and leaves everything inside it alone.
|
|
196
|
-
*/
|
|
197
|
-
export function useAnimationRun({ trigger, play, once, threshold, paused, infinite }) {
|
|
198
|
-
const node = React.useRef(null);
|
|
199
|
-
const [started, setStarted] = React.useState(trigger === 'mount');
|
|
200
|
-
const [run, setRun] = React.useState(0);
|
|
201
|
-
const start = React.useCallback(() => {
|
|
202
|
-
setStarted(true);
|
|
203
|
-
setRun((previous) => previous + 1);
|
|
204
|
-
}, []);
|
|
205
|
-
// Nothing to rewind on the first pass — the element has only just been drawn.
|
|
206
|
-
React.useLayoutEffect(() => {
|
|
207
|
-
const element = node.current;
|
|
208
|
-
if (!element || run === 0) {
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
// The element itself for the effects that animate their own root, and its
|
|
212
|
-
// descendants for the ones that animate their children instead: a staggered
|
|
213
|
-
// PlAnimateAppear has nothing to rewind on its own box.
|
|
214
|
-
const targets = [
|
|
215
|
-
element,
|
|
216
|
-
...element.querySelectorAll('.plass-anim, .plass-marquee-track')
|
|
217
|
-
];
|
|
218
|
-
for (const target of targets) {
|
|
219
|
-
target.style.animationName = 'none';
|
|
220
|
-
}
|
|
221
|
-
void element.offsetWidth;
|
|
222
|
-
for (const target of targets) {
|
|
223
|
-
target.style.animationName = '';
|
|
224
|
-
}
|
|
225
|
-
}, [run]);
|
|
226
|
-
React.useEffect(() => {
|
|
227
|
-
if (trigger !== 'visible') {
|
|
228
|
-
return;
|
|
229
|
-
}
|
|
230
|
-
const element = node.current;
|
|
231
|
-
if (!element || typeof IntersectionObserver === 'undefined') {
|
|
232
|
-
// No observer means no way to know: show it rather than hide it forever.
|
|
233
|
-
setStarted(true);
|
|
234
|
-
return;
|
|
235
|
-
}
|
|
236
|
-
const observer = new IntersectionObserver(([entry]) => {
|
|
237
|
-
if (entry.isIntersecting) {
|
|
238
|
-
start();
|
|
239
|
-
if (once) {
|
|
240
|
-
observer.disconnect();
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
else if (!once) {
|
|
244
|
-
setStarted(false);
|
|
245
|
-
}
|
|
246
|
-
}, { threshold });
|
|
247
|
-
observer.observe(element);
|
|
248
|
-
return () => observer.disconnect();
|
|
249
|
-
}, [trigger, once, threshold, start]);
|
|
250
|
-
React.useEffect(() => {
|
|
251
|
-
if (trigger !== 'manual') {
|
|
252
|
-
return;
|
|
253
|
-
}
|
|
254
|
-
// `play` is a caller pressing go, and what it starts is a CSS animation.
|
|
255
|
-
// There is no external system to push to: the run counter *is* the rewind.
|
|
256
|
-
if (play) {
|
|
257
|
-
// eslint-disable-next-line react-hooks/set-state-in-effect
|
|
258
|
-
start();
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
setStarted(false);
|
|
262
|
-
}
|
|
263
|
-
}, [trigger, play, start]);
|
|
264
|
-
const handlers = trigger === 'hover'
|
|
265
|
-
? {
|
|
266
|
-
onPointerEnter: start,
|
|
267
|
-
// Focus counts, or an effect on something keyboard-reachable would
|
|
268
|
-
// never run for a reader who is not holding a mouse.
|
|
269
|
-
onFocus: start,
|
|
270
|
-
onPointerLeave: () => {
|
|
271
|
-
if (infinite) {
|
|
272
|
-
setStarted(false);
|
|
273
|
-
}
|
|
274
|
-
},
|
|
275
|
-
onBlur: () => {
|
|
276
|
-
if (infinite) {
|
|
277
|
-
setStarted(false);
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
}
|
|
281
|
-
: {};
|
|
282
|
-
return {
|
|
283
|
-
ref: React.useCallback((element) => {
|
|
284
|
-
node.current = element;
|
|
285
|
-
}, []),
|
|
286
|
-
state: started && !paused ? 'running' : 'paused',
|
|
287
|
-
started,
|
|
288
|
-
handlers
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
/**
|
|
292
|
-
* Everything a one-keyframe `PlAnimate*` root needs, in one call.
|
|
293
|
-
*
|
|
294
|
-
* The six effect components differ only in their defaults and in which slots
|
|
295
|
-
* they fill, so this is where the identical two-thirds of each of them lives.
|
|
296
|
-
* The ones that have to understand their children — Appear, Headline, Marquee,
|
|
297
|
-
* Typing — call `useAnimationRun` directly and put the classes where their own
|
|
298
|
-
* structure needs them, which is why `effect` is allowed to be `null`.
|
|
299
|
-
*
|
|
300
|
-
* `data-plass-animation` and `data-state` are here rather than in each
|
|
301
|
-
* component because they are the same two facts every time, and because a test
|
|
302
|
-
* that has to assert on a class name is a test that breaks when a class name
|
|
303
|
-
* changes.
|
|
304
|
-
*/
|
|
305
|
-
export function useAnimateElement(params) {
|
|
306
|
-
const { effect, trigger, play, once, threshold, paused, infinite, ...slots } = params;
|
|
307
|
-
const run = useAnimationRun({ trigger, play, once, threshold, paused, infinite });
|
|
308
|
-
return {
|
|
309
|
-
ref: run.ref,
|
|
310
|
-
className: effect ? `${animBaseClass} ${animationClasses[effect]}` : '',
|
|
311
|
-
style: { ...animationSlots(slots), '--p-anim-state': run.state },
|
|
312
|
-
props: {
|
|
313
|
-
...run.handlers,
|
|
314
|
-
'data-plass-animation': effect ?? undefined,
|
|
315
|
-
'data-state': run.state
|
|
316
|
-
}
|
|
317
|
-
};
|
|
318
|
-
}
|
|
1
|
+
import*as e from"react";export const animationClasses={fade:"plass-anim-fade",grow:"plass-anim-scale",slide:"plass-anim-slide",zoom:"plass-anim-scale",rotate:"plass-anim-rotate",blink:"plass-anim-blink"};export const animBaseClass="plass-anim";export function lengthValue(e){return"number"==typeof e?`${e}px`:e}export function repeatValue(e){return"infinite"===e?"infinite":String(e)}export function isInfinite(e){return"infinite"===e}export function directionValue(e,n){return"out"===e?n?"alternate-reverse":"reverse":n?"alternate":"normal"}export function animationSlots(e){const n={"--p-anim-duration":`${e.duration}ms`,"--p-anim-delay":`${e.delay}ms`,"--p-anim-repeat":repeatValue(e.repeat),"--p-anim-direction":directionValue(e.mode??"in",e.alternate)};return e.easing&&(n["--p-anim-ease"]=e.easing),void 0!==e.opacity&&(n["--p-anim-opacity"]=String(e.opacity)),void 0!==e.scale&&(n["--p-anim-scale"]=String(e.scale)),void 0!==e.x&&(n["--p-anim-x"]=e.x),void 0!==e.y&&(n["--p-anim-y"]=e.y),void 0!==e.angle&&(n["--p-anim-angle"]=e.angle),void 0!==e.angleTo&&(n["--p-anim-angle-to"]=e.angleTo),n}export function slideOffsets(e,n){const t=lengthValue(n),a="number"==typeof n?-n+"px":`calc(-1 * ${t})`;switch(e){case"top":return{x:"0px",y:a};case"bottom":return{x:"0px",y:t};case"left":return{x:a,y:"0px"};default:return{x:t,y:"0px"}}}const n="(prefers-reduced-motion: reduce)";function subscribeToMotion(e){if("undefined"==typeof window||!window.matchMedia)return()=>{};const t=window.matchMedia(n);return t.addEventListener("change",e),()=>t.removeEventListener("change",e)}function readMotion(){return!("undefined"==typeof window||!window.matchMedia)&&window.matchMedia(n).matches}function motionOnServer(){return!1}export function usePrefersReducedMotion(){return e.useSyncExternalStore(subscribeToMotion,readMotion,motionOnServer)}export function useAnimationRun({trigger:n,play:t,once:a,threshold:i,paused:o,infinite:r}){const s=e.useRef(null),[u,c]=e.useState("mount"===n),[l,p]=e.useState(0),d=e.useCallback(()=>{c(!0),p(e=>e+1)},[]);e.useLayoutEffect(()=>{const e=s.current;if(!e||0===l)return;const n=[e,...e.querySelectorAll(".plass-anim, .plass-marquee-track")];for(const e of n)e.style.animationName="none";e.offsetWidth;for(const e of n)e.style.animationName=""},[l]),e.useEffect(()=>{if("visible"!==n)return;const e=s.current;if(!e||"undefined"==typeof IntersectionObserver)return void c(!0);const t=new IntersectionObserver(([e])=>{e.isIntersecting?(d(),a&&t.disconnect()):a||c(!1)},{threshold:i});return t.observe(e),()=>t.disconnect()},[n,a,i,d]),e.useEffect(()=>{"manual"===n&&(t?d():c(!1))},[n,t,d]);const f="hover"===n?{onPointerEnter:d,onFocus:d,onPointerLeave:()=>{r&&c(!1)},onBlur:()=>{r&&c(!1)}}:{};return{ref:e.useCallback(e=>{s.current=e},[]),state:u&&!o?"running":"paused",started:u,handlers:f}}export function useAnimateElement(e){const{effect:n,trigger:t,play:a,once:i,threshold:o,paused:r,infinite:s,...u}=e,c=useAnimationRun({trigger:t,play:a,once:i,threshold:o,paused:r,infinite:s});return{ref:c.ref,className:n?`plass-anim ${animationClasses[n]}`:"",style:{...animationSlots(u),"--p-anim-state":c.state},props:{...c.handlers,"data-plass-animation":n??void 0,"data-state":c.state}}}
|
|
@@ -1,19 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
*
|
|
4
|
-
* A context rather than `React.Children.map` with `cloneElement`, and a file of
|
|
5
|
-
* its own rather than something the group exports, for one reason each.
|
|
6
|
-
*
|
|
7
|
-
* Cloning breaks the moment a caller wraps one of the buttons in a `PlTooltip`,
|
|
8
|
-
* a `<Fragment>` or a `.map()` — which is most of the time — and a context
|
|
9
|
-
* reaches the button wherever it ended up. And it lives here rather than beside
|
|
10
|
-
* the group so that `PlButton` can read it without the two components importing
|
|
11
|
-
* each other, which is the arrangement `internal/menu.ts` already has.
|
|
12
|
-
*
|
|
13
|
-
* Every field is optional, and every one of them means *not specified* rather
|
|
14
|
-
* than a value: a button falls back to its own default, so a `PlButtonGroup`
|
|
15
|
-
* with no props of its own changes nothing except the corners.
|
|
16
|
-
*/
|
|
17
|
-
import * as React from 'react';
|
|
18
|
-
export const ButtonGroupContext =
|
|
19
|
-
/* @__PURE__ */ React.createContext(null);
|
|
1
|
+
import*as t from"react";export const ButtonGroupContext=
|
|
2
|
+
/* @__PURE__ */t.createContext(null);
|