@blukavantui/community 1.0.1 → 1.2.0
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 +11 -5
- package/dist/build-audit.json +234 -44
- package/dist/checkbox.css +1 -0
- package/dist/checkbox.d.ts +2 -0
- package/dist/checkbox.js +1 -0
- package/dist/chunk-2BSBXDOT.js +1 -0
- package/dist/chunk-4LHIQROI.js +0 -0
- package/dist/chunk-5ENZVZGF.js +0 -0
- package/dist/chunk-6T677NSC.js +1 -0
- package/dist/chunk-7CEOCZ5L.js +0 -0
- package/dist/chunk-7DXFNK7C.js +1 -0
- package/dist/chunk-AL2ETLJV.js +1 -0
- package/dist/chunk-BN3PDE5G.js +0 -0
- package/dist/chunk-CNIIMGT3.js +0 -0
- package/dist/chunk-CSTCEBEK.js +1 -0
- package/dist/chunk-DRZM2AL3.js +0 -0
- package/dist/chunk-EOKNLCNS.js +1 -0
- package/dist/chunk-EPPETNK6.js +1 -0
- package/dist/chunk-EPPSBHZR.js +1 -0
- package/dist/chunk-EPZGLHPD.js +0 -0
- package/dist/chunk-FNX33PDD.js +0 -0
- package/dist/{chunk-NTFHNL7T.js → chunk-G6OW4OZM.js} +1 -1
- package/dist/chunk-GS67ZBLI.js +1 -0
- package/dist/chunk-HO6CYWED.js +0 -0
- package/dist/{chunk-6EHKOVZK.js → chunk-HVR2UDFX.js} +1 -1
- package/dist/chunk-IJ62ILKE.js +0 -0
- package/dist/chunk-IKYBFMHI.js +1 -0
- package/dist/chunk-IO22GWON.js +0 -0
- package/dist/chunk-KVOA55NE.js +0 -0
- package/dist/{chunk-MZBB5ROJ.js → chunk-LF2HELEZ.js} +1 -1
- package/dist/chunk-MYVLBALF.js +1 -0
- package/dist/{chunk-UEOCR2C3.js → chunk-OLDA73XG.js} +2 -2
- package/dist/chunk-RWBLICYX.js +0 -0
- package/dist/chunk-RYD6RHRX.js +0 -0
- package/dist/chunk-T45FJNEQ.js +1 -0
- package/dist/chunk-TZSX4OTV.js +1 -0
- package/dist/chunk-UN2SLVFG.js +1 -0
- package/dist/{chunk-GK3INPAZ.js → chunk-V2YPIC6Z.js} +1 -1
- package/dist/chunk-V4ZQLQ7L.js +0 -0
- package/dist/chunk-VAM3FPCS.js +0 -0
- package/dist/chunk-VJVFHL6P.js +0 -0
- package/dist/chunk-VSTKXZYY.js +0 -0
- package/dist/chunk-W3H7XTA7.js +1 -0
- package/dist/chunk-WG4US4JH.js +1 -0
- package/dist/chunk-WGSTNXAQ.js +0 -0
- package/dist/chunk-WJHCVECU.js +1 -0
- package/dist/chunk-XVMJG26X.js +1 -0
- package/dist/chunk-Y4AXWTAD.js +0 -0
- package/dist/chunk-YCLR3IE3.js +0 -0
- package/dist/chunk-YLFXSHKZ.js +0 -0
- package/dist/chunk-ZDGZGAYG.js +0 -0
- package/dist/columns2.css +1 -0
- package/dist/columns2.d.ts +2 -0
- package/dist/columns2.js +1 -0
- package/dist/columns3.css +1 -0
- package/dist/columns3.d.ts +2 -0
- package/dist/columns3.js +1 -0
- package/dist/columns4.css +1 -0
- package/dist/columns4.d.ts +2 -0
- package/dist/columns4.js +1 -0
- package/dist/command-palette.js +1 -1
- package/dist/component-motion.css +39 -0
- package/dist/component-motion.d.ts +45 -0
- package/dist/component-motion.js +1 -0
- package/dist/content.js +1 -1
- package/dist/core.css +8 -0
- package/dist/core.js +1 -1
- package/dist/data-motion.css +4 -0
- package/dist/data-motion.d.ts +23 -0
- package/dist/data-motion.js +1 -0
- package/dist/data.css +63 -0
- package/dist/data.d.ts +1 -0
- package/dist/data.js +1 -1
- package/dist/date-picker.css +5 -5
- package/dist/date-picker.js +1 -1
- package/dist/date-range-picker.css +5 -5
- package/dist/date-range-picker.js +1 -1
- package/dist/date-time-picker.css +5 -5
- package/dist/date-time-picker.js +1 -1
- package/dist/draft-components.json +77 -0
- package/dist/drawer.js +1 -1
- package/dist/essentials.css +8 -0
- package/dist/feedback.js +1 -1
- package/dist/form-field.css +1 -0
- package/dist/form-field.d.ts +2 -0
- package/dist/form-field.js +1 -0
- package/dist/form-layout/choice.d.ts +15 -0
- package/dist/form-layout/layout.d.ts +12 -0
- package/dist/form-layout/select.d.ts +3 -0
- package/dist/form-layout/shared.d.ts +21 -0
- package/dist/form-layout/table.d.ts +20 -0
- package/dist/form-layout/text.d.ts +3 -0
- package/dist/form-layout/types.d.ts +151 -0
- package/dist/form-layout.css +62 -0
- package/dist/form-layout.d.ts +12 -0
- package/dist/form-layout.js +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -1
- package/dist/inputs.css +83 -20
- package/dist/inputs.d.ts +8 -0
- package/dist/inputs.js +1 -1
- package/dist/layout.css +63 -0
- package/dist/layout.d.ts +3 -0
- package/dist/layout.js +1 -1
- package/dist/modal.js +1 -1
- package/dist/motion/action-feedback.d.ts +14 -0
- package/dist/motion/border-glow.d.ts +12 -0
- package/dist/motion/button.d.ts +11 -0
- package/dist/motion/component-settings.d.ts +51 -0
- package/dist/motion/controller.d.ts +33 -0
- package/dist/motion/effects.d.ts +30 -0
- package/dist/motion/feedback.d.ts +6 -0
- package/dist/motion/loading.d.ts +9 -0
- package/dist/motion/optional.d.ts +35 -0
- package/dist/motion/photo.d.ts +7 -0
- package/dist/motion/presence.d.ts +12 -0
- package/dist/motion/scene.d.ts +10 -0
- package/dist/motion/screen.d.ts +6 -0
- package/dist/motion/scroll-reveal.d.ts +13 -0
- package/dist/motion/settings-group.d.ts +14 -0
- package/dist/motion/stagger.d.ts +12 -0
- package/dist/motion/structure.d.ts +18 -0
- package/dist/motion/tabs.d.ts +19 -0
- package/dist/motion/tokens.d.ts +11 -0
- package/dist/motion/value.d.ts +21 -0
- package/dist/motion/view-transition.d.ts +14 -0
- package/dist/motion-enhancers.d.ts +12 -0
- package/dist/motion-enhancers.js +1 -0
- package/dist/motion-settings.d.ts +3 -0
- package/dist/motion-settings.js +1 -0
- package/dist/motion.css +1076 -0
- package/dist/motion.d.ts +20 -0
- package/dist/motion.js +1 -0
- package/dist/native/date-picker.js +1 -1
- package/dist/native/date-range-picker.js +1 -1
- package/dist/native/date-time-picker.js +1 -1
- package/dist/native/form-layout.js +1 -0
- package/dist/native/time-picker.js +1 -1
- package/dist/native-components/form-layout.d.ts +1 -0
- package/dist/native-motion-components.d.ts +3 -0
- package/dist/native-motion-content.d.ts +1 -0
- package/dist/native-motion-foundations.d.ts +3 -0
- package/dist/native-motion-layout.d.ts +3 -0
- package/dist/native-motion-pilot.d.ts +34 -0
- package/dist/native-motion.d.ts +71 -0
- package/dist/notification.js +1 -1
- package/dist/pagination.js +1 -1
- package/dist/radio-button.css +1 -0
- package/dist/radio-button.d.ts +2 -0
- package/dist/radio-button.js +1 -0
- package/dist/radio-group.css +1 -0
- package/dist/radio-group.d.ts +2 -0
- package/dist/radio-group.js +1 -0
- package/dist/select.css +1 -0
- package/dist/select.d.ts +2 -0
- package/dist/select.js +1 -0
- package/dist/sidebar.js +1 -1
- package/dist/sizes.json +416 -112
- package/dist/skeleton.css +8 -0
- package/dist/styles.css +1213 -20
- package/dist/switch.css +1 -0
- package/dist/switch.d.ts +2 -0
- package/dist/switch.js +1 -0
- package/dist/table.css +1 -0
- package/dist/table.d.ts +2 -0
- package/dist/table.js +1 -0
- package/dist/text-area.css +1 -0
- package/dist/text-area.d.ts +2 -0
- package/dist/text-area.js +1 -0
- package/dist/text-input.css +1 -0
- package/dist/text-input.d.ts +2 -0
- package/dist/text-input.js +1 -0
- package/dist/time-picker.css +5 -5
- package/dist/time-picker.js +1 -1
- package/dist/tree-view.js +1 -1
- package/dist/web-motion/chip-ripple.d.ts +6 -0
- package/dist/web-motion/choice-ripple.d.ts +6 -0
- package/dist/web-motion/content.d.ts +9 -0
- package/dist/web-motion/data-rows.d.ts +12 -0
- package/dist/web-motion/fields.d.ts +6 -0
- package/dist/web-motion/navigation.d.ts +6 -0
- package/dist/web-motion/notifications.d.ts +6 -0
- package/dist/web-motion/select-ripple.d.ts +6 -0
- package/dist/web-motion/statistic.d.ts +13 -0
- package/dist/web-motion/surfaces.d.ts +10 -0
- package/dist/web-motion/tree.d.ts +6 -0
- package/docs/FORM-LAYOUT-ESSENTIALS.md +122 -0
- package/docs/PUBLISHING.md +129 -25
- package/draft-components.json +77 -0
- package/edition.json +44 -7
- package/npm-shrinkwrap.json +2 -2
- package/package.json +102 -10
- package/scripts/build-motion-css.mjs +36 -0
- package/scripts/build-motion-styles.mjs +29 -0
- package/scripts/build.mjs +20 -8
- package/scripts/motion-entries.mjs +2 -0
- package/src/checkbox.ts +2 -0
- package/src/columns2.ts +2 -0
- package/src/columns3.ts +2 -0
- package/src/columns4.ts +2 -0
- package/src/component-motion.ts +101 -0
- package/src/data-motion.ts +60 -0
- package/src/data.ts +1 -0
- package/src/form-field.ts +2 -0
- package/src/form-layout/choice.ts +82 -0
- package/src/form-layout/layout.ts +40 -0
- package/src/form-layout/select.ts +97 -0
- package/src/form-layout/shared.ts +57 -0
- package/src/form-layout/table.ts +86 -0
- package/src/form-layout/text.ts +73 -0
- package/src/form-layout/types.ts +59 -0
- package/src/form-layout.ts +12 -0
- package/src/index.ts +2 -0
- package/src/inputs.ts +8 -0
- package/src/layout.ts +3 -0
- package/src/motion/action-feedback.ts +38 -0
- package/src/motion/border-glow.ts +41 -0
- package/src/motion/button.ts +56 -0
- package/src/motion/component-settings.ts +147 -0
- package/src/motion/controller.ts +191 -0
- package/src/motion/effects.ts +75 -0
- package/src/motion/feedback.ts +41 -0
- package/src/motion/loading.ts +40 -0
- package/src/motion/optional.ts +123 -0
- package/src/motion/photo.ts +19 -0
- package/src/motion/presence.ts +44 -0
- package/src/motion/scene.ts +103 -0
- package/src/motion/screen.ts +15 -0
- package/src/motion/scroll-reveal.ts +49 -0
- package/src/motion/settings-group.ts +28 -0
- package/src/motion/stagger.ts +26 -0
- package/src/motion/structure.ts +75 -0
- package/src/motion/tabs.ts +105 -0
- package/src/motion/tokens.ts +2 -0
- package/src/motion/value.ts +61 -0
- package/src/motion/view-transition.ts +57 -0
- package/src/motion-enhancers.ts +12 -0
- package/src/motion-settings.ts +3 -0
- package/src/motion.ts +20 -0
- package/src/native-components/form-layout.ts +21 -0
- package/src/native-motion-components.ts +76 -0
- package/src/native-motion-content.ts +10 -0
- package/src/native-motion-foundations.ts +56 -0
- package/src/native-motion-layout.ts +35 -0
- package/src/native-motion-pilot.ts +151 -0
- package/src/native-motion.ts +188 -0
- package/src/radio-button.ts +2 -0
- package/src/radio-group.ts +2 -0
- package/src/runtime/date-picker.js +21 -12
- package/src/runtime/date-range-picker.js +21 -12
- package/src/runtime/date-time-picker.js +21 -12
- package/src/runtime/time-picker.js +21 -12
- package/src/select.ts +2 -0
- package/src/switch.ts +2 -0
- package/src/table.ts +2 -0
- package/src/text-area.ts +2 -0
- package/src/text-input.ts +2 -0
- package/src/types.ts +0 -12
- package/src/web-motion/chip-ripple.ts +31 -0
- package/src/web-motion/choice-ripple.ts +30 -0
- package/src/web-motion/content.ts +74 -0
- package/src/web-motion/data-rows.ts +106 -0
- package/src/web-motion/fields.ts +52 -0
- package/src/web-motion/navigation.ts +62 -0
- package/src/web-motion/notifications.ts +67 -0
- package/src/web-motion/select-ripple.ts +23 -0
- package/src/web-motion/statistic.ts +23 -0
- package/src/web-motion/surfaces.ts +137 -0
- package/src/web-motion/tree.ts +44 -0
- package/styles/checkbox.css +1 -0
- package/styles/columns2.css +1 -0
- package/styles/columns3.css +1 -0
- package/styles/columns4.css +1 -0
- package/styles/component-motion.css +39 -0
- package/styles/data-motion.css +4 -0
- package/styles/date-picker.css +5 -5
- package/styles/date-range-picker.css +5 -5
- package/styles/date-time-picker.css +5 -5
- package/styles/form-field.css +1 -0
- package/styles/form-layout.css +62 -0
- package/styles/motion-optional.css +15 -0
- package/styles/motion-presets.css +92 -0
- package/styles/motion-tokens.css +6 -0
- package/styles/motion.css +125 -0
- package/styles/radio-button.css +1 -0
- package/styles/radio-group.css +1 -0
- package/styles/select.css +1 -0
- package/styles/skeleton.css +8 -0
- package/styles/switch.css +1 -0
- package/styles/table.css +1 -0
- package/styles/text-area.css +1 -0
- package/styles/text-input.css +1 -0
- package/styles/time-picker.css +5 -5
- package/test/component-motion-settings.test.mjs +35 -0
- package/test/content-overlay-motion.test.mjs +36 -0
- package/test/form-layout.test.mjs +28 -0
- package/test/isolation.test.mjs +2 -2
- package/test/motion.test.mjs +215 -0
- package/dist/chunk-2TCNAQC6.js +0 -1
- package/dist/chunk-CTLZIWMX.js +0 -1
- package/dist/chunk-MHHJZYXW.js +0 -1
- package/dist/chunk-XDYBNO4P.js +0 -1
- /package/dist/{chunk-H7ETPJVW.js → chunk-3PODK22R.js} +0 -0
- /package/dist/{chunk-SIU7DSOA.js → chunk-KBWB4OIF.js} +0 -0
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type {MotionController} from '../motion/controller.js';
|
|
2
|
+
import {createNumberTransition} from '../motion/value.js';
|
|
3
|
+
type Values={Value?:number;Precision?:number;Locale?:string;IsLoading?:boolean};
|
|
4
|
+
/** Exact value remains accessible throughout the decorative number transition. */
|
|
5
|
+
export function enhanceStatistic(root:HTMLElement,motion:MotionController,read:()=>Values) {
|
|
6
|
+
const previousKind=root.getAttribute('data-blu-component-motion');root.setAttribute('data-blu-component-motion','statistic');
|
|
7
|
+
let dead=false,target:HTMLElement|null=null,previous=read().Value??0;
|
|
8
|
+
let number:ReturnType<typeof createNumberTransition>|undefined;
|
|
9
|
+
const sync=()=>{
|
|
10
|
+
if(dead)return;
|
|
11
|
+
const next=root.querySelector<HTMLElement>('.blu-statistic__value > strong');
|
|
12
|
+
if(next===target)return;
|
|
13
|
+
number?.destroy();number=undefined;target=next;
|
|
14
|
+
if(!next)return;
|
|
15
|
+
const options=read(),value=Number(options.Value??0);
|
|
16
|
+
if(!Number.isFinite(value))return;
|
|
17
|
+
const formatter=new Intl.NumberFormat(options.Locale||'en-US',{minimumFractionDigits:options.Precision??0,maximumFractionDigits:options.Precision??0});
|
|
18
|
+
number=createNumberTransition(next,motion,{value:previous,format:v=>formatter.format(v)});
|
|
19
|
+
void number.set(value,{duration:750,easing:'ease-in-out'});previous=value;
|
|
20
|
+
};
|
|
21
|
+
sync();const observer=new MutationObserver(sync);observer.observe(root,{childList:true,subtree:true});
|
|
22
|
+
return {capture(){},destroy(){if(dead)return;dead=true;observer.disconnect();number?.destroy();if(previousKind===null)root.removeAttribute('data-blu-component-motion');else root.setAttribute('data-blu-component-motion',previousKind);}};
|
|
23
|
+
}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type { MotionController, MotionEffect } from '../motion/controller.js';
|
|
2
|
+
|
|
3
|
+
/** Existing components own focus trapping, dismissal and events; the first dialog
|
|
4
|
+
* presentation receives named context after paint. A closing surface is an inert,
|
|
5
|
+
* short-lived visual copy; its bounds are frozen so focus restoration cannot reflow it.
|
|
6
|
+
*/
|
|
7
|
+
export function observeSurface(root: HTMLElement, motion: MotionController, kind: 'modal' | 'drawer' | 'palette' | 'select' | 'picker' | 'cascader' | 'tree-select') {
|
|
8
|
+
const previous = root.getAttribute('data-blu-surface-motion'); root.setAttribute('data-blu-surface-motion', kind);
|
|
9
|
+
const selector = kind === 'cascader' ? '.blu-cascader__popup' : kind === 'tree-select' ? '.blu-tree-select__popup' : kind === 'picker' ? '.blu-picker__popup' : kind === 'select' ? '.blu-select__popup' : kind === 'palette' ? '.blu-command__dialog' : '.blu-overlay';
|
|
10
|
+
let target: HTMLElement | null = null, wasOpen = false, destroyed = false, revision = 0, trackingFrame = 0, exitDeadline = 0;
|
|
11
|
+
let dialogFocusFrame = 0, dialogPresented = false;
|
|
12
|
+
let ghost: HTMLElement | null = null, ghostTargets: HTMLElement[] = [], rect: DOMRect | undefined, panelRect: DOMRect | undefined;
|
|
13
|
+
let font = '', background = '', color = '', backdrop = '#18223066', blur = 'none', opacity = '1', panelOpacity = '1', scrollPositions: number[] = [];
|
|
14
|
+
const win = root.ownerDocument.defaultView!;
|
|
15
|
+
function isOpen(node: HTMLElement) { return kind === 'palette' ? (node as HTMLDialogElement).open : !node.hidden; }
|
|
16
|
+
function entrance(): MotionEffect {
|
|
17
|
+
if (kind !== 'drawer') return kind === 'modal' ? 'scale' : 'slide-down';
|
|
18
|
+
return target?.dataset.placement === 'left' ? 'slide-right' : target?.dataset.placement === 'bottom' ? 'slide-up' : 'slide-left';
|
|
19
|
+
}
|
|
20
|
+
function remember() {
|
|
21
|
+
if (!target || !isOpen(target)) return;
|
|
22
|
+
const panel = target.querySelector<HTMLElement>('.blu-overlay__panel') || target;
|
|
23
|
+
rect = target.getBoundingClientRect(); panelRect = panel.getBoundingClientRect();
|
|
24
|
+
const css = win.getComputedStyle(target); font = css.font; background = css.backgroundColor; color = css.color;
|
|
25
|
+
opacity = panel === target ? '1' : css.opacity; panelOpacity = win.getComputedStyle(panel).opacity;
|
|
26
|
+
if (kind === 'palette') { const scrim = win.getComputedStyle(target, '::backdrop'); backdrop = scrim.backgroundColor; blur = scrim.backdropFilter; }
|
|
27
|
+
scrollPositions = [target, ...Array.from(target.querySelectorAll<HTMLElement>('*'))].map(el => el.scrollTop);
|
|
28
|
+
}
|
|
29
|
+
function stopTracking() { win.cancelAnimationFrame(trackingFrame); trackingFrame = 0; }
|
|
30
|
+
function cancelDialogFocus() { win.cancelAnimationFrame(dialogFocusFrame); dialogFocusFrame = 0; }
|
|
31
|
+
function clearGhost() {
|
|
32
|
+
++revision;
|
|
33
|
+
win.clearTimeout(exitDeadline); exitDeadline = 0;
|
|
34
|
+
for (const element of ghostTargets) motion.cancel(element); ghostTargets = [];
|
|
35
|
+
ghost?.remove(); ghost = null;
|
|
36
|
+
}
|
|
37
|
+
function frozenBounds(element: HTMLElement, box: DOMRect) {
|
|
38
|
+
Object.assign(element.style, { position: 'fixed', boxSizing: 'border-box', inset: 'auto', left: box.left + 'px', top: box.top + 'px', width: box.width + 'px', height: box.height + 'px', maxWidth: 'none', maxHeight: 'none', margin: '0', transform: 'none' });
|
|
39
|
+
}
|
|
40
|
+
function closingCopy(node: HTMLElement) {
|
|
41
|
+
if (node.ownerDocument.querySelector('.blu-overlay:not([hidden]):not([data-blu-exit-visual]), dialog[open]')) return;
|
|
42
|
+
if (!rect?.width || !rect.height || !node.isConnected || node.querySelector('video,canvas,iframe')) return;
|
|
43
|
+
const copy = node.cloneNode(true) as HTMLElement;
|
|
44
|
+
const sourceNodes = [node, ...Array.from(node.querySelectorAll<HTMLElement>('*'))], copyNodes = [copy, ...Array.from(copy.querySelectorAll<HTMLElement>('*'))];
|
|
45
|
+
copyNodes.forEach((el, index) => {
|
|
46
|
+
if (index && el.hasAttribute('popover')) el.hidden = true;
|
|
47
|
+
for (const name of ['id','name','autofocus','popover','aria-live','aria-labelledby','aria-describedby','aria-controls']) el.removeAttribute(name);
|
|
48
|
+
// Inert + no names prevent interaction/submission. Preserve enabled styles to avoid a flash.
|
|
49
|
+
if (el instanceof HTMLInputElement) { const source = sourceNodes[index] as HTMLInputElement; el.value = source.type === 'password' ? '' : source.value; el.checked = source.checked; }
|
|
50
|
+
else if (el instanceof HTMLTextAreaElement || el instanceof HTMLSelectElement) el.value = (sourceNodes[index] as HTMLTextAreaElement).value;
|
|
51
|
+
el.style.pointerEvents = 'none';
|
|
52
|
+
});
|
|
53
|
+
copy.hidden = false; copy.inert = true; copy.setAttribute('aria-hidden', 'true');
|
|
54
|
+
const parent = node.parentElement!;
|
|
55
|
+
if (kind === 'modal' || kind === 'drawer') { ghost = copy; parent.append(copy); }
|
|
56
|
+
else {
|
|
57
|
+
const portal = node.ownerDocument.createElement('div');
|
|
58
|
+
portal.className = kind === 'palette' ? 'blu-command blu-motion-exit-surface' : 'blu-motion-exit-surface';
|
|
59
|
+
portal.style.cssText = `position:fixed;inset:0;width:100vw;height:100dvh;margin:0;padding:0;border:0;max-width:none;max-height:none;background:${kind === 'palette' ? backdrop : 'transparent'};backdrop-filter:${kind === 'palette' ? blur : 'none'};overflow:visible;pointer-events:none;`;
|
|
60
|
+
if (kind === 'palette') {
|
|
61
|
+
const surface = node.ownerDocument.createElement('div'); surface.className = copy.className; surface.append(...Array.from(copy.childNodes));
|
|
62
|
+
frozenBounds(surface, rect); Object.assign(surface.style, { background, color, font }); portal.append(surface);
|
|
63
|
+
} else { frozenBounds(copy, rect); copy.style.font = font; portal.append(copy); }
|
|
64
|
+
ghost = portal; parent.append(portal);
|
|
65
|
+
}
|
|
66
|
+
ghost.dataset.bluExitVisual = kind; ghost.inert = true; ghost.setAttribute('aria-hidden', 'true'); ghost.style.pointerEvents = 'none';
|
|
67
|
+
ghost.setAttribute('popover', 'manual');
|
|
68
|
+
if (ghost.showPopover) { try { ghost.showPopover(); } catch { ghost.removeAttribute('popover'); } }
|
|
69
|
+
const visual = ghost.querySelector<HTMLElement>('.blu-overlay__panel, .blu-command__dialog, .blu-select__popup, .blu-picker__popup') || ghost;
|
|
70
|
+
if (panelRect && (kind === 'modal' || kind === 'drawer')) frozenBounds(visual, panelRect);
|
|
71
|
+
visual.style.opacity = panelOpacity;
|
|
72
|
+
copyNodes.forEach((el, index) => { el.scrollTop = scrollPositions[index] || 0; });
|
|
73
|
+
// Fade exactly one layer. Fading both the parent and child multiplies opacity and
|
|
74
|
+
// makes the content disappear ahead of its backdrop. Popup exits do not rescale.
|
|
75
|
+
const own = revision, tasks = [motion.animate(ghost, [{ opacity }, { opacity: 0 }], { phase: 'exit', duration: 450, easing: 'ease-in-out' }, 'fade')];
|
|
76
|
+
ghostTargets = [ghost];
|
|
77
|
+
if (kind === 'drawer') {
|
|
78
|
+
const direction = node.dataset.placement === 'left' ? 'translateX(-18px)' : node.dataset.placement === 'bottom' ? 'translateY(18px)' : 'translateX(18px)';
|
|
79
|
+
ghostTargets.push(visual);
|
|
80
|
+
tasks.push(motion.animate(visual, [{ transform: 'none' }, { transform: direction }], { duration: 450, easing: 'ease-in-out' }));
|
|
81
|
+
}
|
|
82
|
+
// Some browsers suspend WAAPI for off-screen/inert top-layer visuals. The
|
|
83
|
+
// real popup has already closed; never let a paused cosmetic copy linger.
|
|
84
|
+
exitDeadline = win.setTimeout(() => { if (!destroyed && own === revision) clearGhost(); }, (motion.resolveOptions?.({ duration: 450 }).duration ?? (motion.mode === 'full' ? 450 : 200)) + 250);
|
|
85
|
+
void Promise.all(tasks).finally(() => { if (!destroyed && own === revision) clearGhost(); });
|
|
86
|
+
}
|
|
87
|
+
const resize = new ResizeObserver(() => { if (wasOpen) remember(); });
|
|
88
|
+
function sync() {
|
|
89
|
+
if (destroyed) return;
|
|
90
|
+
const next = root.matches(selector) ? root : root.querySelector<HTMLElement>(selector);
|
|
91
|
+
if (target !== next) { if (target) resize.unobserve(target); target = next; wasOpen = false; if (target) resize.observe(target); }
|
|
92
|
+
if (!target) return;
|
|
93
|
+
const open = isOpen(target);
|
|
94
|
+
if (open === wasOpen) return;
|
|
95
|
+
wasOpen = open; stopTracking(); cancelDialogFocus(); clearGhost();
|
|
96
|
+
const panel = target.querySelector<HTMLElement>('.blu-overlay__panel') || target;
|
|
97
|
+
motion.cancel(panel); motion.cancel(target);
|
|
98
|
+
if (open) {
|
|
99
|
+
remember(); const own = revision;
|
|
100
|
+
// Safari can announce only "button" when focus enters a newly exposed
|
|
101
|
+
// popover before its dialog subtree has reached the accessibility tree.
|
|
102
|
+
// On the first presentation, focus the named dialog after paint. Never
|
|
103
|
+
// override navigation the user has already made inside that dialog.
|
|
104
|
+
if ((kind === 'modal' || kind === 'drawer') && !dialogPresented) {
|
|
105
|
+
const initialFocus = root.ownerDocument.activeElement;
|
|
106
|
+
dialogFocusFrame = win.requestAnimationFrame(() => {
|
|
107
|
+
dialogFocusFrame = win.requestAnimationFrame(() => {
|
|
108
|
+
dialogFocusFrame = 0;
|
|
109
|
+
if (destroyed || !wasOpen || own !== revision) return;
|
|
110
|
+
dialogPresented = true;
|
|
111
|
+
if (panel.contains(initialFocus) && root.ownerDocument.activeElement === initialFocus) panel.focus({ preventScroll: true });
|
|
112
|
+
});
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
const tasks = [motion.play(panel, entrance(), { duration: kind === 'drawer' ? 450 : 350, easing: 'ease-out' })];
|
|
116
|
+
if (panel !== target) tasks.push(motion.play(target, 'fade', { duration: 280 }));
|
|
117
|
+
// ResizeObserver does not observe transforms. Track opening frames and record
|
|
118
|
+
// the final resting bounds, rather than reusing a partly translated/scaled box.
|
|
119
|
+
const trackOpening = () => { if (destroyed || !wasOpen || own !== revision) return; remember(); trackingFrame = win.requestAnimationFrame(trackOpening); };
|
|
120
|
+
trackingFrame = win.requestAnimationFrame(trackOpening);
|
|
121
|
+
void Promise.all(tasks).then(() => { if (!destroyed && wasOpen && own === revision) { stopTracking(); remember(); } });
|
|
122
|
+
} else if (motion.mode !== 'off' && !root.closest('.blu-motion-off, [data-blu-motion="off"]')) closingCopy(target);
|
|
123
|
+
}
|
|
124
|
+
const observer = new MutationObserver(sync);
|
|
125
|
+
observer.observe(root, { subtree: true, childList: true, attributes: true, attributeFilter: ['hidden', 'open'] });
|
|
126
|
+
const track = () => { if (wasOpen) remember(); };
|
|
127
|
+
win.addEventListener('resize', track); win.addEventListener('scroll', track, true);
|
|
128
|
+
root.ownerDocument.addEventListener('pointerdown', track, true); root.ownerDocument.addEventListener('keydown', track, true);
|
|
129
|
+
sync();
|
|
130
|
+
return { sync, capture: remember, destroy() {
|
|
131
|
+
if (destroyed) return; destroyed = true; stopTracking(); cancelDialogFocus(); observer.disconnect(); resize.disconnect(); clearGhost();
|
|
132
|
+
if (previous === null) root.removeAttribute('data-blu-surface-motion'); else root.setAttribute('data-blu-surface-motion', previous);
|
|
133
|
+
win.removeEventListener('resize', track); win.removeEventListener('scroll', track, true);
|
|
134
|
+
root.ownerDocument.removeEventListener('pointerdown', track, true); root.ownerDocument.removeEventListener('keydown', track, true);
|
|
135
|
+
if (target) { motion.cancel(target); const panel = target.querySelector<HTMLElement>('.blu-overlay__panel'); if (panel) motion.cancel(panel); }
|
|
136
|
+
} };
|
|
137
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { MotionController } from '../motion/controller.js';
|
|
2
|
+
import { preserveStyles } from '../motion/structure.js';
|
|
3
|
+
|
|
4
|
+
/** The tree runtime owns hidden/expanded state and keyboard navigation. During a
|
|
5
|
+
* full-motion collapse only, keep the inert visual in layout until it reaches zero. */
|
|
6
|
+
export function enhanceTree(root: HTMLElement, motion: MotionController) {
|
|
7
|
+
const previous = root.getAttribute('data-blu-component-motion'); root.setAttribute('data-blu-component-motion', 'tree');
|
|
8
|
+
type State = { open: boolean; height: number; revision: number; release(): void };
|
|
9
|
+
const groups = new Map<HTMLElement, State>(); let dead = false;
|
|
10
|
+
const resize = new ResizeObserver(entries => {
|
|
11
|
+
for (const entry of entries) { const el = entry.target as HTMLElement, state = groups.get(el); if (state && (!el.hidden || el.style.display === 'block')) state.height = el.getBoundingClientRect().height; }
|
|
12
|
+
});
|
|
13
|
+
function sync() {
|
|
14
|
+
if (dead) return;
|
|
15
|
+
for (const [group, state] of groups) if (!root.contains(group)) { ++state.revision; motion.cancel(group); state.release(); resize.unobserve(group); groups.delete(group); }
|
|
16
|
+
for (const group of root.querySelectorAll<HTMLElement>('.blu-tree__group')) {
|
|
17
|
+
let state = groups.get(group);
|
|
18
|
+
if (!state) { state = { open: !group.hidden, height: group.getBoundingClientRect().height, revision: 0, release() {} }; groups.set(group, state); resize.observe(group); continue; }
|
|
19
|
+
const open = !group.hidden;
|
|
20
|
+
if (state.open === open) continue;
|
|
21
|
+
const from = state.height, own = ++state.revision;
|
|
22
|
+
state.open = open; motion.cancel(group); state.release(); state.release = () => {};
|
|
23
|
+
if (group.parentElement?.closest('[hidden]')) continue;
|
|
24
|
+
const full = motion.mode === 'full' && !group.closest('.blu-motion-off,[data-blu-motion=off],[data-blu-motion=reduced]');
|
|
25
|
+
if (!full) { if (open) void motion.play(group, 'fade', { duration: 350 }); continue; }
|
|
26
|
+
const restore = preserveStyles(group, ['display', 'overflow', 'height']);
|
|
27
|
+
const inert = group.inert, ariaHidden = group.getAttribute('aria-hidden');
|
|
28
|
+
state.release = () => { restore(); group.inert = inert; if (ariaHidden === null) group.removeAttribute('aria-hidden'); else group.setAttribute('aria-hidden', ariaHidden); };
|
|
29
|
+
if (!open) { group.inert = true; group.setAttribute('aria-hidden', 'true'); group.style.setProperty('display', 'block', 'important'); }
|
|
30
|
+
const to = open ? group.scrollHeight : 0;
|
|
31
|
+
group.style.overflow = 'hidden'; group.style.height = to + 'px';
|
|
32
|
+
void motion.animate(group, [{ height: from + 'px' }, { height: to + 'px' }], { duration: 650, easing: 'ease-in-out' }).then(() => {
|
|
33
|
+
if (!dead && state!.revision === own) { state!.release(); state!.release = () => {}; state!.height = group.getBoundingClientRect().height; }
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
const observer = new MutationObserver(sync); sync();
|
|
38
|
+
observer.observe(root, { subtree: true, childList: true, attributes: true, attributeFilter: ['hidden'] });
|
|
39
|
+
return { destroy() {
|
|
40
|
+
if (dead) return; dead = true; observer.disconnect(); resize.disconnect();
|
|
41
|
+
for (const [group, state] of groups) { ++state.revision; motion.cancel(group); state.release(); } groups.clear();
|
|
42
|
+
if (previous === null) root.removeAttribute('data-blu-component-motion'); else root.setAttribute('data-blu-component-motion', previous);
|
|
43
|
+
} };
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import './form-layout.css';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import './form-layout.css';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import './form-layout.css';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import './form-layout.css';
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/* Opt-in web motion. Existing components remain unchanged without the integration. */
|
|
2
|
+
[data-blu-component-motion=field] :is(.blu-text,.blu-textarea,.blu-select__trigger,.blu-choice__mark,.blu-text__action){transition:background-color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),border-color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),box-shadow var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease)}
|
|
3
|
+
[data-blu-component-motion=field] .blu-choice--switch .blu-choice__mark::after{transition:transform var(--blu-component-motion-duration,320ms) var(--blu-component-motion-ease,cubic-bezier(.2,.8,.2,1))}
|
|
4
|
+
[data-blu-component-motion=field] .blu-choice--radio .blu-choice__mark::after{content:'';width:7px;height:7px;border-radius:50%;background:currentColor;transform:scale(0);transition:transform var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease-out)}
|
|
5
|
+
[data-blu-component-motion=field] .blu-choice--radio input:checked+.blu-choice__mark::after{transform:scale(1)}
|
|
6
|
+
[data-blu-component-motion=field] .blu-select__trigger::after{transition:transform var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease-out)}
|
|
7
|
+
[data-blu-component-motion=field] .blu-select__trigger[aria-expanded=true]::after{transform:translateY(2px) rotate(225deg)}
|
|
8
|
+
[data-blu-exit-visual] :disabled{opacity:1!important}
|
|
9
|
+
/* Focus rings and validation semantics stay immediate; only decorative feedback moves. */
|
|
10
|
+
:is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) [data-blu-component-motion=field] *,
|
|
11
|
+
:is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) [data-blu-component-motion=field] *::after{transition:none!important;animation:none!important}
|
|
12
|
+
@media(prefers-reduced-motion:reduce){[data-blu-component-motion=field] *,[data-blu-component-motion=field] *::after{transition:none!important;animation:none!important}}
|
|
13
|
+
[data-blu-surface-motion] :is(.blu-select__option,.blu-command__option,.blu-control){transition:background-color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),border-color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease)}
|
|
14
|
+
:is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) [data-blu-surface-motion] *{transition:none!important}
|
|
15
|
+
@media(prefers-reduced-motion:reduce){[data-blu-surface-motion] *{transition:none!important}}
|
|
16
|
+
/* Side drawers meet both viewport edges; the content scrolls between fixed header/footer. */
|
|
17
|
+
[data-blu-surface-motion=drawer].blu-overlay:is([data-placement=left],[data-placement=right]){padding:0;align-items:stretch}
|
|
18
|
+
[data-blu-surface-motion=drawer].blu-overlay:is([data-placement=left],[data-placement=right])>.blu-overlay__panel{margin:0;height:100dvh;max-height:100dvh;min-height:0;border-radius:0}
|
|
19
|
+
[data-blu-surface-motion=drawer] :is(.blu-overlay__header,.blu-overlay__footer){flex-shrink:0}
|
|
20
|
+
/* Existing notification keyframes are replaced by the scoped controller. */
|
|
21
|
+
[data-blu-component-motion=notifications] .blu-notification{animation:none}
|
|
22
|
+
[data-blu-component-motion=tree] .blu-tree__row{transition:background-color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease)}
|
|
23
|
+
[data-blu-surface-motion=picker] :is(.blu-picker__button,.blu-picker__input,.blu-picker__day){transition:background-color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),border-color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease),color var(--blu-component-motion-duration,280ms) var(--blu-component-motion-ease,ease)}
|
|
24
|
+
:is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) [data-blu-component-motion=tree] *{transition:none!important}
|
|
25
|
+
@media(prefers-reduced-motion:reduce){[data-blu-component-motion=tree] *{transition:none!important}}
|
|
26
|
+
/* Web-only active-location markers: existing links retain focus and behavior. */
|
|
27
|
+
.blu-motion-navigation-marker{position:absolute;display:block;border-radius:3px;background:var(--bluui-primary,#5144ed);pointer-events:none;transform-origin:top left;z-index:1}
|
|
28
|
+
.blu-motion-navigation-marker[hidden]{display:none}
|
|
29
|
+
.blu-motion-navigation-marker[data-kind=pagination]{box-sizing:border-box;border:2px solid var(--bluui-primary,#5144ed);border-radius:8px;background:transparent}
|
|
30
|
+
[data-blu-navigation-motion] .blu-navigation-menu .blu-navigation-menu__link--active{color:var(--bluui-primary,#5144ed);background:var(--bluui-color-primary-soft,#efedff)}
|
|
31
|
+
@media(forced-colors:active){.blu-motion-navigation-marker{background:Highlight}}
|
|
32
|
+
@media(forced-colors:active){.blu-motion-navigation-marker[data-kind=pagination]{background:transparent;border-color:Highlight}}
|
|
33
|
+
|
|
34
|
+
/* Shared finite transition settings; continuous loading keeps its own cadence. */
|
|
35
|
+
.blu-motion-button.blu-button{transition-duration:var(--blu-component-motion-duration,var(--blu-motion-duration));transition-timing-function:var(--blu-component-motion-ease,var(--blu-motion-ease))}
|
|
36
|
+
/* A preference may sit on the component root itself, not only its parent. */
|
|
37
|
+
:is([data-blu-component-motion],[data-blu-surface-motion],[data-blu-navigation-motion]):is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) *,
|
|
38
|
+
:is([data-blu-component-motion],[data-blu-surface-motion],[data-blu-navigation-motion]):is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) *::before,
|
|
39
|
+
:is([data-blu-component-motion],[data-blu-surface-motion],[data-blu-navigation-motion]):is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) *::after{transition:none!important;animation:none!important}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
.blu-data-motion-exits { position: absolute; inset: 0; overflow: hidden; pointer-events: none; z-index: 3; border-radius: inherit; }
|
|
2
|
+
.blu-data-motion-exit { position: absolute; display: grid; background: var(--bluui-surface, #fff); color: var(--bluui-text-muted, #68758b); font-size: 13px; align-items: center; border-bottom: 1px solid var(--bluui-border, #dce3ed); pointer-events: none; }
|
|
3
|
+
.blu-data-motion-exit > span { padding: 10px 12px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
|
|
4
|
+
@media (forced-colors: active) { .blu-data-motion-exits { display: none; } }
|
package/styles/date-picker.css
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
.blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
|
|
7
7
|
.blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
|
|
8
8
|
.blu-picker__field {flex:1 1 180px;min-width:0;}
|
|
9
|
-
.blu-picker__field label,.blu-picker__select-
|
|
9
|
+
.blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
|
|
10
10
|
.blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
|
|
11
11
|
.blu-picker__field-control {position:relative;}
|
|
12
12
|
.blu-picker__field-control>.blu-picker__input {padding-right:38px;}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
.blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
|
|
30
30
|
.blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
|
|
31
31
|
.blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
|
|
32
|
-
.blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr)
|
|
32
|
+
.blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
|
|
33
33
|
.blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
|
|
34
34
|
.blu-picker__select-field {min-width:0;}
|
|
35
35
|
.blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
/* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
|
|
55
55
|
.blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
|
|
56
56
|
.blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
|
|
57
|
-
.blu-picker__dialog .blu-picker__select-
|
|
58
|
-
.blu-picker__calendar-nav .blu-picker__select-
|
|
57
|
+
.blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
|
|
58
|
+
.blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
|
|
59
59
|
.blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
|
|
60
60
|
@media(pointer:coarse){
|
|
61
61
|
.blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
.blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
|
|
73
73
|
.blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
|
|
74
74
|
.blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
|
|
75
|
-
.blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-
|
|
75
|
+
.blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
|
|
76
76
|
.blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
|
|
77
77
|
.blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
|
|
78
78
|
.blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
.blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
|
|
7
7
|
.blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
|
|
8
8
|
.blu-picker__field {flex:1 1 180px;min-width:0;}
|
|
9
|
-
.blu-picker__field label,.blu-picker__select-
|
|
9
|
+
.blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
|
|
10
10
|
.blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
|
|
11
11
|
.blu-picker__field-control {position:relative;}
|
|
12
12
|
.blu-picker__field-control>.blu-picker__input {padding-right:38px;}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
.blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
|
|
30
30
|
.blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
|
|
31
31
|
.blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
|
|
32
|
-
.blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr)
|
|
32
|
+
.blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
|
|
33
33
|
.blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
|
|
34
34
|
.blu-picker__select-field {min-width:0;}
|
|
35
35
|
.blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
/* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
|
|
55
55
|
.blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
|
|
56
56
|
.blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
|
|
57
|
-
.blu-picker__dialog .blu-picker__select-
|
|
58
|
-
.blu-picker__calendar-nav .blu-picker__select-
|
|
57
|
+
.blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
|
|
58
|
+
.blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
|
|
59
59
|
.blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
|
|
60
60
|
@media(pointer:coarse){
|
|
61
61
|
.blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
.blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
|
|
73
73
|
.blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
|
|
74
74
|
.blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
|
|
75
|
-
.blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-
|
|
75
|
+
.blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
|
|
76
76
|
.blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
|
|
77
77
|
.blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
|
|
78
78
|
.blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
.blu-picker [hidden],.blu-picker__dialog [hidden] {display:none!important;}
|
|
7
7
|
.blu-picker__fields {display:flex;flex-wrap:wrap;gap:12px;}
|
|
8
8
|
.blu-picker__field {flex:1 1 180px;min-width:0;}
|
|
9
|
-
.blu-picker__field label,.blu-picker__select-
|
|
9
|
+
.blu-picker__field label,.blu-picker__select-caption {display:block;margin-bottom:5px;color:var(--bluui-text,#182230);font-weight:600;}
|
|
10
10
|
.blu-picker__input {display:block;width:100%;min-width:0;min-height:42px;padding:9px 11px;border:1px solid var(--bluui-control-border,#69788d);border-radius:9px;background:var(--bluui-surface,#fff);color:var(--bluui-text,#182230);font:inherit;line-height:1.4;}
|
|
11
11
|
.blu-picker__field-control {position:relative;}
|
|
12
12
|
.blu-picker__field-control>.blu-picker__input {padding-right:38px;}
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
.blu-picker__dialog::backdrop {background:transparent;pointer-events:none;}
|
|
30
30
|
.blu-picker__dialog-head {display:flex;align-items:center;justify-content:space-between;gap:16px;margin-bottom:14px;}
|
|
31
31
|
.blu-picker__dialog-head h2 {font-size:16px;line-height:1.4;font-family:var(--blu-font-heading-family,inherit);margin:0;overflow-wrap:anywhere;}
|
|
32
|
-
.blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr)
|
|
32
|
+
.blu-picker__calendar-nav {display:grid;grid-template-columns:32px minmax(0,1fr) 88px 32px;align-items:end;gap:6px;margin-top:0;}
|
|
33
33
|
.blu-picker__calendar-nav>.blu-picker__button {height:36px;padding:2px;font-size:22px;}
|
|
34
34
|
.blu-picker__select-field {min-width:0;}
|
|
35
35
|
.blu-picker__caption {font-size:15px;text-align:center;margin:16px 0 8px;}
|
|
@@ -54,8 +54,8 @@
|
|
|
54
54
|
/* Compact popup controls; editable text stays at 16px to avoid iOS focus zoom. */
|
|
55
55
|
.blu-picker__dialog .blu-picker__input {min-height:36px;padding:5px 7px;font-size:16px;line-height:1.2;}
|
|
56
56
|
.blu-picker__dialog .blu-picker__button {min-height:34px;min-width:32px;padding:5px 9px;font-size:13px;line-height:1.25;}
|
|
57
|
-
.blu-picker__dialog .blu-picker__select-
|
|
58
|
-
.blu-picker__calendar-nav .blu-picker__select-
|
|
57
|
+
.blu-picker__dialog .blu-picker__select-caption {font-size:11px;margin-bottom:2px;}
|
|
58
|
+
.blu-picker__calendar-nav .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
|
|
59
59
|
.blu-picker__dialog .blu-picker__error {margin-top:4px;font-size:12px;line-height:1.3;}
|
|
60
60
|
@media(pointer:coarse){
|
|
61
61
|
.blu-picker__field-control>.blu-picker__input {font-size:16px;min-height:44px;}
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
.blu-picker__dialog[data-compact=true] .blu-picker__calendar td {height:24px;}
|
|
73
73
|
.blu-picker__dialog[data-compact=true] .blu-picker__day {min-height:24px;padding:3px 0;}
|
|
74
74
|
.blu-picker__dialog[data-compact=true] .blu-picker__time-area {margin:4px 0;gap:6px;}
|
|
75
|
-
.blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-
|
|
75
|
+
.blu-picker__dialog[data-compact=true] .blu-picker__time-area .blu-picker__select-caption {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;}
|
|
76
76
|
.blu-picker__dialog[data-compact=true] .blu-picker__selection {position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap;margin:0;}
|
|
77
77
|
.blu-picker__dialog[data-compact=true] .blu-picker__popup-actions {margin-top:4px;gap:4px;}
|
|
78
78
|
.blu-picker__dialog[data-compact=true] .blu-picker__presets {margin-bottom:4px;gap:4px;}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
@import './form-layout.css';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/* Community Form & Layout Essentials — local draft; no OutSystems UI selectors. */
|
|
2
|
+
.blu-field,.blu-columns,.blu-table{box-sizing:border-box;min-width:0;color:var(--bluui-text,#182230);font-family:var(--blu-font-family,Inter,system-ui,sans-serif);font-size:14px}
|
|
3
|
+
.blu-field *,.blu-columns *,.blu-table *{box-sizing:border-box}
|
|
4
|
+
.blu-field [hidden],.blu-table [hidden]{display:none!important}
|
|
5
|
+
.blu-field{--blu-field-height:42px;--blu-field-padding:12px;display:flex;flex-direction:column;gap:7px;border:0;padding:0;margin:0;min-inline-size:0}
|
|
6
|
+
.blu-field--small{--blu-field-height:34px;--blu-field-padding:9px;font-size:13px}.blu-field--large{--blu-field-height:50px;--blu-field-padding:15px;font-size:16px}
|
|
7
|
+
.blu-field__label{font-weight:600;line-height:1.5;padding:0;margin:0 0 2px}.blu-field__body{min-width:0}
|
|
8
|
+
.blu-field__help,.blu-choice__description,.blu-field__count{font-size:12px;color:var(--bluui-text-muted,#5c6b80);line-height:1.5}.blu-field__error{color:var(--bluui-color-error-text,#b42318);font-size:12px;line-height:1.5}.blu-field__count{text-align:end;margin-top:5px;font-variant-numeric:tabular-nums}
|
|
9
|
+
.blu-text,.blu-textarea,.blu-select__trigger{border:1px solid var(--bluui-control-border,#7b8799);border-radius:var(--blu-radius-md,8px);background:var(--bluui-surface,#fff);color:inherit;transition:border-color .12s,box-shadow .12s}
|
|
10
|
+
.blu-text{display:flex;align-items:center;gap:8px;min-height:var(--blu-field-height);padding:0 var(--blu-field-padding)}
|
|
11
|
+
.blu-text__input{width:100%;min-width:0;border:0!important;box-shadow:none!important;outline:none!important;background:transparent!important;color:inherit;padding:9px 0!important;font:inherit;line-height:1.5;height:auto}
|
|
12
|
+
.blu-text__input::placeholder,.blu-textarea::placeholder{color:var(--bluui-text-muted,#5c6b80);opacity:1}
|
|
13
|
+
.blu-text:focus-within,.blu-textarea:focus-visible,.blu-select__trigger:focus-visible{border-color:var(--bluui-primary,#4f46e5);outline:2px solid var(--bluui-primary,#4f46e5);outline-offset:2px}
|
|
14
|
+
.blu-text__adornment{display:inline-flex;flex:none;gap:6px;align-items:center;color:var(--bluui-text-muted,#5c6b80);white-space:nowrap}.blu-text__adornment img{width:24px;height:24px;object-fit:contain;border-radius:4px}
|
|
15
|
+
.blu-text__action{display:inline-flex;align-items:center;justify-content:center;border:0;border-radius:4px;background:transparent;color:var(--bluui-primary,#4f46e5);font:inherit;font-size:12px;font-weight:600;min-width:26px;min-height:30px;cursor:pointer;white-space:nowrap;padding:3px}
|
|
16
|
+
.blu-text__action:hover{background:var(--bluui-hover,#f0f2f7)}
|
|
17
|
+
.blu-field button:focus-visible,.blu-table button:focus-visible,.blu-table__scroll:focus-visible{outline:2px solid var(--bluui-primary,#4f46e5);outline-offset:3px}
|
|
18
|
+
.blu-textarea{display:block;width:100%;min-height:var(--blu-field-height);padding:10px var(--blu-field-padding);font:inherit;line-height:1.6}
|
|
19
|
+
.blu-field[data-invalid=true] .blu-text,.blu-field[data-invalid=true] .blu-textarea,.blu-field[data-invalid=true] .blu-select__trigger{border-color:var(--bluui-color-error-text,#b42318)}
|
|
20
|
+
.blu-field[data-disabled=true]{opacity:.6}.blu-field input:disabled,.blu-field textarea:disabled,.blu-field button:disabled{cursor:not-allowed}
|
|
21
|
+
.blu-field input[readonly],.blu-field textarea[readonly]{cursor:default}
|
|
22
|
+
.blu-choice{display:flex;align-items:center;position:relative;gap:10px;min-height:32px;cursor:pointer;line-height:1.5}.blu-choice__input{position:absolute;inline-size:1px;block-size:1px;clip-path:inset(50%);overflow:hidden;white-space:nowrap;opacity:0}
|
|
23
|
+
.blu-choice__mark{display:inline-flex;flex-shrink:0;align-items:center;justify-content:center;width:19px;height:19px;border:1.5px solid var(--bluui-control-border,#7b8799);border-radius:5px;background:var(--bluui-surface,#fff);color:var(--bluui-on-primary,#fff)}
|
|
24
|
+
.blu-choice__input:checked+.blu-choice__mark,.blu-choice__input:indeterminate+.blu-choice__mark{background:var(--bluui-primary,#4f46e5);border-color:var(--bluui-primary,#4f46e5)}
|
|
25
|
+
.blu-choice--checkbox .blu-choice__input:checked+.blu-choice__mark:after{content:'';width:5px;height:9px;border:solid currentColor;border-width:0 2px 2px 0;transform:translateY(-1px) rotate(45deg)}
|
|
26
|
+
.blu-choice__input:indeterminate+.blu-choice__mark:after{content:'';width:9px;height:2px;background:currentColor;transform:none;border:0}
|
|
27
|
+
.blu-choice__input:focus-visible+.blu-choice__mark{outline:2px solid var(--bluui-primary,#4f46e5);outline-offset:3px}
|
|
28
|
+
.blu-choice:has(input:disabled){opacity:.6;cursor:not-allowed}.blu-field[data-disabled=true] .blu-choice:has(input:disabled){opacity:1}
|
|
29
|
+
.blu-choice--radio .blu-choice__mark{border-radius:50%}.blu-choice--radio .blu-choice__input:checked+.blu-choice__mark:after{content:'';width:7px;height:7px;border-radius:50%;background:currentColor}
|
|
30
|
+
.blu-choice--switch .blu-choice__mark{width:38px;height:22px;border-radius:20px;background:var(--bluui-control-border,#7b8799);padding:2px;justify-content:flex-start}
|
|
31
|
+
.blu-choice--switch .blu-choice__mark:after{content:'';height:16px;width:16px;background:#fff;border-radius:50%;transition:transform .15s}
|
|
32
|
+
.blu-choice--switch .blu-choice__input:checked+.blu-choice__mark:after{transform:translateX(14px)}.blu-choice--switch .blu-choice__input:checked+.blu-choice__mark{background:var(--bluui-primary,#4f46e5)}
|
|
33
|
+
.blu-choice__state{margin-inline-start:auto;font-size:12px;color:var(--bluui-text-muted,#5c6b80)}.blu-choice__description{display:block}
|
|
34
|
+
.blu-radio-group{display:flex;flex-direction:column;gap:10px}.blu-radio-group--horizontal{flex-direction:row;flex-wrap:wrap;gap:12px 24px}
|
|
35
|
+
.blu-select{position:relative;display:flex;gap:5px}.blu-select__native{position:absolute;width:1px;height:1px;opacity:0;clip-path:inset(50%);pointer-events:none}
|
|
36
|
+
.blu-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:10px;min-width:0;min-height:var(--blu-field-height);width:100%;padding:9px var(--blu-field-padding);font:inherit;text-align:start;cursor:pointer}
|
|
37
|
+
.blu-select__trigger:after{content:'';width:7px;height:7px;border:solid currentColor;border-width:0 1.5px 1.5px 0;transform:translateY(-2px) rotate(45deg);flex-shrink:0}.blu-select__trigger[data-placeholder=true]{color:var(--bluui-text-muted,#5c6b80)}
|
|
38
|
+
.blu-select__popup{box-sizing:border-box;position:absolute;inset:calc(100% + 6px) 0 auto;z-index:1000;max-height:320px;overflow:auto;margin:0;padding:6px;border:1px solid var(--bluui-border-strong,#b8c4d4);border-radius:10px;background:var(--bluui-surface,#fff);box-shadow:var(--bluui-menu-shadow,0 10px 30px #17203326);color:var(--bluui-text,#182230);font:inherit}
|
|
39
|
+
.blu-select__search{width:100%;min-height:38px;padding:8px 10px;border:1px solid var(--bluui-control-border,#7b8799);border-radius:6px;background:var(--bluui-surface,#fff);color:inherit;font:inherit;margin-bottom:5px;outline-offset:2px}
|
|
40
|
+
.blu-select__option{padding:9px 10px;border-radius:5px;cursor:pointer;line-height:1.5}.blu-select__option[aria-selected=true]{font-weight:600;color:var(--bluui-primary,#4f46e5)}.blu-select__option[data-active=true]{background:var(--bluui-selected,#e9e6ff)}.blu-select__option[aria-disabled=true]{opacity:.5;cursor:not-allowed}
|
|
41
|
+
.blu-columns{display:grid;grid-template-columns:var(--blu-columns-tracks,1fr 1fr);gap:var(--blu-columns-gap,24px)}.blu-columns__column{min-width:0;display:flex;flex-direction:column;gap:20px}
|
|
42
|
+
@media(max-width:479px){.blu-columns--stack-small{grid-template-columns:minmax(0,1fr)}}
|
|
43
|
+
@media(max-width:767px){.blu-columns--stack-medium{grid-template-columns:minmax(0,1fr)}}
|
|
44
|
+
@media(max-width:1023px){.blu-columns--stack-large{grid-template-columns:minmax(0,1fr)}}
|
|
45
|
+
.blu-table{border:1px solid var(--bluui-border,#e2e8f0);border-radius:12px;background:var(--bluui-surface,#fff);overflow:hidden}
|
|
46
|
+
.blu-table__scroll{overflow:auto}.blu-table table{width:100%;border-collapse:collapse;font:inherit;text-align:start}.blu-table caption{text-align:start;padding:18px;font-weight:600;font-size:15px}
|
|
47
|
+
.blu-table th{font-size:12px;color:var(--bluui-text-muted,#5c6b80);background:var(--bluui-surface-muted,#f7f8fb);font-weight:600;white-space:nowrap}
|
|
48
|
+
.blu-table th,.blu-table td{padding:14px 18px;border-top:1px solid var(--bluui-border,#e2e8f0);line-height:1.5}
|
|
49
|
+
.blu-table[data-density=Compact] th,.blu-table[data-density=Compact] td{padding:8px 12px}
|
|
50
|
+
.blu-table[data-striped=true] tbody tr:nth-child(even){background:var(--bluui-surface-muted,#f7f8fb)}
|
|
51
|
+
.blu-table__sort{font:inherit;font-weight:600;color:inherit;background:transparent;border:0;padding:0;cursor:pointer;display:inline-flex;align-items:center;gap:12px}
|
|
52
|
+
.blu-table__empty{text-align:center!important;height:140px;color:var(--bluui-text-muted,#5c6b80)}
|
|
53
|
+
.blu-table__footer{display:flex;align-items:center;gap:8px;padding:12px 18px;border-top:1px solid var(--bluui-border,#e2e8f0);font-size:12px;flex-wrap:wrap}.blu-table__footer>span{margin-inline-end:auto;color:var(--bluui-text-muted,#5c6b80)}
|
|
54
|
+
.blu-table-button{border:1px solid var(--bluui-border-strong,#b8c4d4);border-radius:6px;padding:6px 10px;background:var(--bluui-surface,#fff);font:inherit;font-size:12px;color:var(--bluui-text,#182230);cursor:pointer;min-height:30px;white-space:nowrap}.blu-table-button:hover{background:var(--bluui-hover,#f0f2f7)}.blu-table-button:disabled{opacity:.5;cursor:not-allowed}.blu-table__actions{display:flex;gap:6px}
|
|
55
|
+
@media(prefers-reduced-motion:reduce){.blu-field *{transition:none!important}}
|
|
56
|
+
@media(forced-colors:active){.blu-choice__mark{forced-color-adjust:none;border-color:ButtonText;background:Canvas;color:HighlightText}.blu-choice__input:checked+.blu-choice__mark,.blu-choice__input:indeterminate+.blu-choice__mark{background:Highlight;border-color:Highlight}.blu-select__option[data-active=true]{outline:2px solid Highlight}.blu-choice--switch .blu-choice__mark:after{background:ButtonText}.blu-choice--switch .blu-choice__input:checked+.blu-choice__mark:after{background:HighlightText}}
|
|
57
|
+
|
|
58
|
+
/* Equal height is row-scoped; stacked columns retain their content height. */
|
|
59
|
+
.blu-columns.blu-columns--equal-height{align-items:stretch}
|
|
60
|
+
.blu-columns--equal-height > .blu-columns__column > :only-child{flex:1 1 auto}
|
|
61
|
+
.blu-columns--equal-height > .blu-columns__column > [data-placeholder]{display:flex;flex-direction:column}
|
|
62
|
+
.blu-columns--equal-height > .blu-columns__column > [data-placeholder] > :only-child{flex:1 1 auto}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/* Opt-in decoration. Layers never consume pointer events or enter the accessibility tree. */
|
|
2
|
+
.blu-motion-ripple,.blu-motion-shimmer{position:absolute;inset:0;overflow:hidden;border-radius:inherit;pointer-events:none!important}
|
|
3
|
+
.blu-motion-ripple__wave{position:absolute;border-radius:50%;background:var(--blu-ripple-color,currentColor);pointer-events:none!important;opacity:0}
|
|
4
|
+
.blu-motion-choice-ripple{inset:-10px;border-radius:999px;--blu-ripple-color:var(--bluui-primary,#4f46e5)}
|
|
5
|
+
.blu-motion-shimmer__beam{position:absolute;inset:0;background:linear-gradient(100deg,transparent 20%,var(--blu-shimmer-color,#ffffffb8) 50%,transparent 80%);animation:blu-motion-shimmer var(--blu-shimmer-duration,1800ms) ease-in-out infinite}
|
|
6
|
+
@keyframes blu-motion-shimmer{from{transform:translateX(-100%)}to{transform:translateX(100%)}}
|
|
7
|
+
.blu-motion-shimmer[data-paused=true] .blu-motion-shimmer__beam{animation-play-state:paused}
|
|
8
|
+
.blu-motion-icon{display:block;width:24px;height:24px;overflow:visible;fill:none;stroke:currentColor;stroke-width:1.8;stroke-linecap:round;stroke-linejoin:round;pointer-events:none}
|
|
9
|
+
.blu-motion-emphasis{position:absolute;pointer-events:none!important;color:var(--blu-emphasis-color,currentColor)}
|
|
10
|
+
.blu-motion-emphasis--underline{inset:auto 0 0;height:2px;background:currentColor;transform-origin:left center;border-radius:2px}
|
|
11
|
+
.blu-motion-emphasis--border{inset:0;border-radius:inherit}
|
|
12
|
+
.blu-motion-emphasis--border svg{display:block;width:100%;height:100%;fill:none;stroke:currentColor;stroke-width:2px}
|
|
13
|
+
:is([data-blu-motion=reduced],[data-blu-motion=off],.blu-motion-off) :is(.blu-motion-shimmer__beam,.blu-motion-ripple__wave){display:none;animation:none!important}
|
|
14
|
+
@media(prefers-reduced-motion:reduce){.blu-motion-shimmer__beam,.blu-motion-ripple__wave{display:none;animation:none!important}}
|
|
15
|
+
@media(forced-colors:active){.blu-motion-shimmer__beam,.blu-motion-ripple__wave{display:none}.blu-motion-emphasis{color:Highlight}}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/* Generated by scripts/build-motion-css.mjs. Edit src/motion/effects.ts, then regenerate. */
|
|
2
|
+
.blu-motion-enter-fade, .blu-motion-fade-in { animation: blu-motion-enter-fade var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
3
|
+
@keyframes blu-motion-enter-fade { 0% { opacity: 0; } 100% { opacity: 1; } }
|
|
4
|
+
.blu-motion-exit-fade, .blu-motion-fade-out { animation: blu-motion-exit-fade var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
5
|
+
@keyframes blu-motion-exit-fade { 0% { opacity: 1; } 100% { opacity: 0; } }
|
|
6
|
+
.blu-motion-enter-slide-up, .blu-motion-slide-up { animation: blu-motion-enter-slide-up var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
7
|
+
@keyframes blu-motion-enter-slide-up { 0% { opacity: 0; transform: translateY(var(--blu-motion-distance)); } 100% { opacity: 1; transform: none; } }
|
|
8
|
+
.blu-motion-exit-slide-up { animation: blu-motion-exit-slide-up var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
9
|
+
@keyframes blu-motion-exit-slide-up { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(calc(-1 * var(--blu-motion-distance))); } }
|
|
10
|
+
.blu-motion-enter-slide-down { animation: blu-motion-enter-slide-down var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
11
|
+
@keyframes blu-motion-enter-slide-down { 0% { opacity: 0; transform: translateY(calc(-1 * var(--blu-motion-distance))); } 100% { opacity: 1; transform: none; } }
|
|
12
|
+
.blu-motion-exit-slide-down { animation: blu-motion-exit-slide-down var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
13
|
+
@keyframes blu-motion-exit-slide-down { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateY(var(--blu-motion-distance)); } }
|
|
14
|
+
.blu-motion-enter-slide-left { animation: blu-motion-enter-slide-left var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
15
|
+
@keyframes blu-motion-enter-slide-left { 0% { opacity: 0; transform: translateX(var(--blu-motion-distance)); } 100% { opacity: 1; transform: none; } }
|
|
16
|
+
.blu-motion-exit-slide-left { animation: blu-motion-exit-slide-left var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
17
|
+
@keyframes blu-motion-exit-slide-left { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateX(calc(-1 * var(--blu-motion-distance))); } }
|
|
18
|
+
.blu-motion-enter-slide-right { animation: blu-motion-enter-slide-right var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
19
|
+
@keyframes blu-motion-enter-slide-right { 0% { opacity: 0; transform: translateX(calc(-1 * var(--blu-motion-distance))); } 100% { opacity: 1; transform: none; } }
|
|
20
|
+
.blu-motion-exit-slide-right { animation: blu-motion-exit-slide-right var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
21
|
+
@keyframes blu-motion-exit-slide-right { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: translateX(var(--blu-motion-distance)); } }
|
|
22
|
+
.blu-motion-enter-zoom-in, .blu-motion-scale-in { animation: blu-motion-enter-zoom-in var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
23
|
+
@keyframes blu-motion-enter-zoom-in { 0% { opacity: 0; transform: scale(.92); } 100% { opacity: 1; transform: none; } }
|
|
24
|
+
.blu-motion-exit-zoom-in { animation: blu-motion-exit-zoom-in var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
25
|
+
@keyframes blu-motion-exit-zoom-in { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: scale(1.08); } }
|
|
26
|
+
.blu-motion-enter-zoom-out { animation: blu-motion-enter-zoom-out var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
27
|
+
@keyframes blu-motion-enter-zoom-out { 0% { opacity: 0; transform: scale(1.08); } 100% { opacity: 1; transform: none; } }
|
|
28
|
+
.blu-motion-exit-zoom-out { animation: blu-motion-exit-zoom-out var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
29
|
+
@keyframes blu-motion-exit-zoom-out { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: scale(.92); } }
|
|
30
|
+
.blu-motion-enter-rotate-left { animation: blu-motion-enter-rotate-left var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
31
|
+
@keyframes blu-motion-enter-rotate-left { 0% { opacity: 0; transform: rotate(8deg) scale(.97); } 100% { opacity: 1; transform: none; } }
|
|
32
|
+
.blu-motion-exit-rotate-left { animation: blu-motion-exit-rotate-left var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
33
|
+
@keyframes blu-motion-exit-rotate-left { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: rotate(-8deg) scale(.97); } }
|
|
34
|
+
.blu-motion-enter-rotate-right { animation: blu-motion-enter-rotate-right var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
35
|
+
@keyframes blu-motion-enter-rotate-right { 0% { opacity: 0; transform: rotate(-8deg) scale(.97); } 100% { opacity: 1; transform: none; } }
|
|
36
|
+
.blu-motion-exit-rotate-right { animation: blu-motion-exit-rotate-right var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
37
|
+
@keyframes blu-motion-exit-rotate-right { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: rotate(8deg) scale(.97); } }
|
|
38
|
+
.blu-motion-enter-flip-x { animation: blu-motion-enter-flip-x var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
39
|
+
@keyframes blu-motion-enter-flip-x { 0% { opacity: 0; transform: perspective(600px) rotateX(30deg); } 100% { opacity: 1; transform: none; } }
|
|
40
|
+
.blu-motion-exit-flip-x { animation: blu-motion-exit-flip-x var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
41
|
+
@keyframes blu-motion-exit-flip-x { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: perspective(600px) rotateX(-30deg); } }
|
|
42
|
+
.blu-motion-enter-flip-y { animation: blu-motion-enter-flip-y var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
43
|
+
@keyframes blu-motion-enter-flip-y { 0% { opacity: 0; transform: perspective(600px) rotateY(30deg); } 100% { opacity: 1; transform: none; } }
|
|
44
|
+
.blu-motion-exit-flip-y { animation: blu-motion-exit-flip-y var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
45
|
+
@keyframes blu-motion-exit-flip-y { 0% { opacity: 1; transform: none; } 100% { opacity: 0; transform: perspective(600px) rotateY(-30deg); } }
|
|
46
|
+
.blu-motion-enter-pop { animation: blu-motion-enter-pop var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
47
|
+
@keyframes blu-motion-enter-pop { 0% { opacity: 0; transform: scale(.9); } 72% { opacity: 1; transform: scale(1.025); } 100% { opacity: 1; transform: scale(1); } }
|
|
48
|
+
.blu-motion-exit-pop { animation: blu-motion-exit-pop var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
49
|
+
@keyframes blu-motion-exit-pop { 0% { opacity: 1; transform: scale(1); } 25% { opacity: 1; transform: scale(1.025); } 100% { opacity: 0; transform: scale(.9); } }
|
|
50
|
+
.blu-motion-enter-bounce { animation: blu-motion-enter-bounce var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
51
|
+
@keyframes blu-motion-enter-bounce { 0% { opacity: 0; transform: translateY(var(--blu-motion-distance)); } 72% { opacity: 1; transform: translateY(-3px); } 100% { opacity: 1; transform: translateY(0); } }
|
|
52
|
+
.blu-motion-exit-bounce { animation: blu-motion-exit-bounce var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
53
|
+
@keyframes blu-motion-exit-bounce { 0% { opacity: 1; transform: translateY(0); } 25% { opacity: 1; transform: translateY(-3px); } 100% { opacity: 0; transform: translateY(var(--blu-motion-distance)); } }
|
|
54
|
+
.blu-motion-enter-wipe-up { animation: blu-motion-enter-wipe-up var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
55
|
+
@keyframes blu-motion-enter-wipe-up { 0% { opacity: 0; clip-path: inset(100% 0 0 0); } 100% { opacity: 1; clip-path: inset(0 0 0 0); } }
|
|
56
|
+
.blu-motion-exit-wipe-up { animation: blu-motion-exit-wipe-up var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
57
|
+
@keyframes blu-motion-exit-wipe-up { 0% { opacity: 1; clip-path: inset(0 0 0 0); } 100% { opacity: 0; clip-path: inset(0 0 100% 0); } }
|
|
58
|
+
.blu-motion-enter-wipe-down { animation: blu-motion-enter-wipe-down var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
59
|
+
@keyframes blu-motion-enter-wipe-down { 0% { opacity: 0; clip-path: inset(0 0 100% 0); } 100% { opacity: 1; clip-path: inset(0 0 0 0); } }
|
|
60
|
+
.blu-motion-exit-wipe-down { animation: blu-motion-exit-wipe-down var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
61
|
+
@keyframes blu-motion-exit-wipe-down { 0% { opacity: 1; clip-path: inset(0 0 0 0); } 100% { opacity: 0; clip-path: inset(100% 0 0 0); } }
|
|
62
|
+
.blu-motion-enter-wipe-left { animation: blu-motion-enter-wipe-left var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
63
|
+
@keyframes blu-motion-enter-wipe-left { 0% { opacity: 0; clip-path: inset(0 0 0 100%); } 100% { opacity: 1; clip-path: inset(0 0 0 0); } }
|
|
64
|
+
.blu-motion-exit-wipe-left { animation: blu-motion-exit-wipe-left var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
65
|
+
@keyframes blu-motion-exit-wipe-left { 0% { opacity: 1; clip-path: inset(0 0 0 0); } 100% { opacity: 0; clip-path: inset(0 100% 0 0); } }
|
|
66
|
+
.blu-motion-enter-wipe-right { animation: blu-motion-enter-wipe-right var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
67
|
+
@keyframes blu-motion-enter-wipe-right { 0% { opacity: 0; clip-path: inset(0 100% 0 0); } 100% { opacity: 1; clip-path: inset(0 0 0 0); } }
|
|
68
|
+
.blu-motion-exit-wipe-right { animation: blu-motion-exit-wipe-right var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
69
|
+
@keyframes blu-motion-exit-wipe-right { 0% { opacity: 1; clip-path: inset(0 0 0 0); } 100% { opacity: 0; clip-path: inset(0 0 0 100%); } }
|
|
70
|
+
.blu-motion-enter-circle-reveal { animation: blu-motion-enter-circle-reveal var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
71
|
+
@keyframes blu-motion-enter-circle-reveal { 0% { opacity: 0; clip-path: circle(0% at 50% 50%); } 100% { opacity: 1; clip-path: circle(72% at 50% 50%); } }
|
|
72
|
+
.blu-motion-exit-circle-reveal { animation: blu-motion-exit-circle-reveal var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
73
|
+
@keyframes blu-motion-exit-circle-reveal { 0% { opacity: 1; clip-path: circle(72% at 50% 50%); } 100% { opacity: 0; clip-path: circle(0% at 50% 50%); } }
|
|
74
|
+
.blu-motion-enter-blur-clear { animation: blu-motion-enter-blur-clear var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
75
|
+
@keyframes blu-motion-enter-blur-clear { 0% { opacity: 0; filter: blur(6px); } 100% { opacity: 1; filter: blur(0px); } }
|
|
76
|
+
.blu-motion-exit-blur-clear { animation: blu-motion-exit-blur-clear var(--blu-motion-duration) var(--blu-motion-ease) var(--blu-motion-delay) both; }
|
|
77
|
+
@keyframes blu-motion-exit-blur-clear { 0% { opacity: 1; filter: blur(0px); } 100% { opacity: 0; filter: blur(6px); } }
|
|
78
|
+
.blu-motion-ease-standard { --blu-motion-ease: cubic-bezier(.2,.8,.2,1); }
|
|
79
|
+
.blu-motion-ease-in { --blu-motion-ease: cubic-bezier(.42,0,1,1); }
|
|
80
|
+
.blu-motion-ease-out { --blu-motion-ease: cubic-bezier(0,0,.58,1); }
|
|
81
|
+
.blu-motion-ease-in-out { --blu-motion-ease: cubic-bezier(.42,0,.58,1); }
|
|
82
|
+
.blu-motion-ease-linear { --blu-motion-ease: linear; }
|
|
83
|
+
.blu-motion-ease-spring { --blu-motion-ease: cubic-bezier(.34,1.25,.64,1); }
|
|
84
|
+
.blu-motion-origin-center { transform-origin: 50% 50%; }
|
|
85
|
+
.blu-motion-origin-top { transform-origin: 50% 0%; }
|
|
86
|
+
.blu-motion-origin-bottom { transform-origin: 50% 100%; }
|
|
87
|
+
.blu-motion-origin-left { transform-origin: 0% 50%; }
|
|
88
|
+
.blu-motion-origin-right { transform-origin: 100% 50%; }
|
|
89
|
+
.blu-motion-origin-top-left { transform-origin: 0% 0%; }
|
|
90
|
+
.blu-motion-origin-top-right { transform-origin: 100% 0%; }
|
|
91
|
+
.blu-motion-origin-bottom-left { transform-origin: 0% 100%; }
|
|
92
|
+
.blu-motion-origin-bottom-right { transform-origin: 100% 100%; }
|