@pathscale/ui 2.11.8 → 2.11.10

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.
Files changed (31) hide show
  1. package/dist/components/button/Button.css +10 -2
  2. package/dist/components/color-wheel/ColorWheel.generated.js +4 -1
  3. package/dist/components/color-wheel/ComplexColorWheel.css +1 -1
  4. package/dist/components/color-wheel/ComplexColorWheel.generated.js +180 -173
  5. package/dist/components/color-wheel-flower/ColorWheelFlower.css +84 -4
  6. package/dist/components/color-wheel-flower/ColorWheelFlower.generated.d.ts +2 -0
  7. package/dist/components/color-wheel-flower/ColorWheelFlower.generated.js +25 -248
  8. package/dist/components/dropdown/Dropdown.generated.js +5 -3
  9. package/dist/components/inline-edit/InlineEdit.generated.js +19 -15
  10. package/dist/components/language-switcher/LanguageSwitcher.generated.d.ts +3 -1
  11. package/dist/components/language-switcher/LanguageSwitcher.generated.js +97 -49
  12. package/dist/components/language-switcher/LanguageSwitcher.recipe.d.ts +1 -0
  13. package/dist/components/language-switcher/LanguageSwitcher.recipe.js +8 -2
  14. package/dist/components/language-switcher/createI18n.js +0 -2
  15. package/dist/components/panel-toggle/PanelToggle.css +72 -0
  16. package/dist/components/panel-toggle/PanelToggle.generated.d.ts +18 -0
  17. package/dist/components/panel-toggle/PanelToggle.generated.js +41 -0
  18. package/dist/components/panel-toggle/PanelToggle.recipe.d.ts +21 -0
  19. package/dist/components/panel-toggle/PanelToggle.recipe.js +45 -0
  20. package/dist/components/panel-toggle/index.d.ts +2 -0
  21. package/dist/components/panel-toggle/index.js +2 -0
  22. package/dist/components/select/Select.generated.js +116 -88
  23. package/dist/components/slider/Slider.generated.js +11 -4
  24. package/dist/components/tabs/Tabs.css +5 -0
  25. package/dist/components/tabs/Tabs.generated.js +4 -3
  26. package/dist/index.d.ts +1 -0
  27. package/dist/index.js +1 -0
  28. package/dist/layouts.manifest.json +4 -1
  29. package/dist/motion/engine.js +11 -5
  30. package/dist/purge-manifest.json +108 -9
  31. package/package.json +5 -4
@@ -1,4 +1,4 @@
1
- import { createComponent, insert, memo, mergeProps, ref, spread, template } from "@solidjs/web";
1
+ import { createComponent, insert, memo, mergeProps, spread, template } from "@solidjs/web";
2
2
  import { defineComponent } from "solid-layouts/solid-2/application-boundary";
3
3
  import "./ColorWheelFlower.css";
4
4
  import { For, createMemo, createSignal, createTrackedEffect, onCleanup } from "solid-js";
@@ -9,7 +9,7 @@ import color_swatch_picker from "../color-swatch-picker/index.js";
9
9
  import { useColorPickerContext } from "./colorWheelFlowerContext.js";
10
10
  import { createColorFromHsl, parseColor, rgbToHex, rgbToHsl } from "./ColorUtils.js";
11
11
  import { resolveColorWheelFlowerPalette } from "./ColorWheelFlower.palette.js";
12
- import { motionDistances, motionDurations, motionEasings, prefersReducedMotion, runMotion } from "../../motion/index.js";
12
+ import { prefersReducedMotion } from "../../motion/index.js";
13
13
  import { CLASSES, componentRecipe } from "./ColorWheelFlower.recipe.js";
14
14
  import { flowerPetalPosition } from "./ColorWheelFlower.geometry.js";
15
15
  var _tmpl$ = /*#__PURE__*/ template("<div><div><div><div>"), _tmpl$2 = /*#__PURE__*/ template("<div><div><div><span></span><span>");
@@ -52,67 +52,6 @@ const createColorItem = (id, color, offsetX, offsetY, options)=>{
52
52
  isCenter: options?.isCenter
53
53
  };
54
54
  };
55
- const readMotionState = (el)=>{
56
- if ("u" < typeof getComputedStyle) return {
57
- opacity: 1,
58
- x: 0,
59
- y: 0,
60
- scale: 1
61
- };
62
- const styles = getComputedStyle(el);
63
- const opacityValue = Number.parseFloat(styles.opacity);
64
- const opacity = Number.isFinite(opacityValue) ? opacityValue : 1;
65
- const transform = styles.transform;
66
- if (!transform || "none" === transform) return {
67
- opacity,
68
- x: 0,
69
- y: 0,
70
- scale: 1
71
- };
72
- if ("u" > typeof DOMMatrixReadOnly) {
73
- const matrix = new DOMMatrixReadOnly(transform);
74
- return {
75
- opacity,
76
- x: matrix.m41,
77
- y: matrix.m42,
78
- scale: matrix.a
79
- };
80
- }
81
- const matrixMatch = transform.match(/matrix\(([^)]+)\)/);
82
- if (!matrixMatch) return {
83
- opacity,
84
- x: 0,
85
- y: 0,
86
- scale: 1
87
- };
88
- const values = matrixMatch[1].split(",").map((value)=>Number.parseFloat(value.trim()));
89
- return {
90
- opacity,
91
- scale: Number.isFinite(values[0]) ? values[0] : 1,
92
- x: Number.isFinite(values[4]) ? values[4] : 0,
93
- y: Number.isFinite(values[5]) ? values[5] : 0
94
- };
95
- };
96
- const applyMotionState = (el, state)=>{
97
- el.style.opacity = String(state.opacity ?? 1);
98
- el.style.transform = `translate3d(${state.x ?? 0}px, ${state.y ?? 0}px, 0) scale(${state.scale ?? 1})`;
99
- };
100
- const getLiftOffset = (item, distance)=>{
101
- const radius = Math.sqrt(item.offsetX ** 2 + item.offsetY ** 2);
102
- if (!Number.isFinite(radius) || 0 === radius) return {
103
- x: 0,
104
- y: 0
105
- };
106
- return {
107
- x: item.offsetX / radius * distance,
108
- y: item.offsetY / radius * distance
109
- };
110
- };
111
- const easeOutBack = (overshoot = 1.4)=>(t)=>{
112
- const c1 = overshoot;
113
- const c3 = c1 + 1;
114
- return 1 + c3 * (t - 1) ** 3 + c1 * (t - 1) ** 2;
115
- };
116
55
  const toRgba = (rgb, alpha)=>{
117
56
  const match = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
118
57
  if (!match) return rgb;
@@ -291,19 +230,9 @@ function buildColors(palette) {
291
230
  } : void 0));
292
231
  }
293
232
  const CENTER_INDEX = LAYOUT.findIndex((l)=>l.isCenter);
294
- const MAX_RADIUS = Math.max(...LAYOUT.map((l)=>Math.sqrt(l.offsetX ** 2 + l.offsetY ** 2)));
295
- const MAX_WAVE_DISTANCE = 2 * MAX_RADIUS;
296
- const MAX_WAVE_DELAY = 0.12;
297
233
  const __solidLayoutColorWheelFlower = (_stable, p)=>{
298
234
  const context = useColorPickerContext();
299
235
  const [selectedIndex, setSelectedIndex] = createSignal(null);
300
- const [hoveredIndex, setHoveredIndex] = createSignal(null);
301
- const [pressedIndex, setPressedIndex] = createSignal(null);
302
- const [pointer, setPointer] = createSignal({
303
- x: 0,
304
- y: 0,
305
- active: false
306
- });
307
236
  const [pulseState, setPulseState] = createSignal(null);
308
237
  const [currentTheme, setCurrentTheme] = createSignal("u" > typeof document && "dark" === document.documentElement.getAttribute("data-theme") ? "dark" : "light");
309
238
  if ("u" > typeof window && "u" > typeof MutationObserver) {
@@ -322,12 +251,6 @@ const __solidLayoutColorWheelFlower = (_stable, p)=>{
322
251
  const mode = ()=>p.mode ?? currentTheme();
323
252
  const colors = createMemo(()=>buildColors(resolveColorWheelFlowerPalette(mode(), p.palette)));
324
253
  const reduceMotion = prefersReducedMotion();
325
- reduceMotion || (motionDurations.slow, motionEasings.inOut);
326
- const hoverLift = reduceMotion ? 0 : motionDistances.sm;
327
- const pressScale = 0.96;
328
- const pulseScale = 1.12;
329
- let containerRef;
330
- let pointerTimeout;
331
254
  let pulseTimeout;
332
255
  const closestIndex = createMemo(()=>{
333
256
  const current = context.color();
@@ -401,48 +324,20 @@ const __solidLayoutColorWheelFlower = (_stable, p)=>{
401
324
  if (!selectedItem) return;
402
325
  if (!isNearColor(current, selectedItem)) setSelectedIndex(null);
403
326
  });
404
- const handlePointerMove = (event)=>{
405
- const node = containerRef;
406
- if (!node) return;
407
- const rect = node.getBoundingClientRect();
408
- const x = event.clientX - rect.left - rect.width / 2;
409
- const y = event.clientY - rect.top - rect.height / 2;
410
- setPointer({
411
- x,
412
- y,
413
- active: true
414
- });
415
- if (void 0 !== pointerTimeout) clearTimeout(pointerTimeout);
416
- pointerTimeout = window.setTimeout(()=>{
417
- setPointer((prev)=>({
418
- ...prev,
419
- active: false
420
- }));
421
- }, 120);
422
- };
423
- const handlePointerLeave = ()=>{
424
- setPointer((prev)=>({
425
- ...prev,
426
- active: false
427
- }));
428
- setHoveredIndex(null);
429
- if (void 0 !== pointerTimeout) clearTimeout(pointerTimeout);
430
- };
431
327
  onCleanup(()=>{
432
328
  if (void 0 !== pulseTimeout) clearTimeout(pulseTimeout);
433
- if (void 0 !== pointerTimeout) clearTimeout(pointerTimeout);
434
329
  });
435
330
  const pickerValue = ()=>colors()[visualSelectedIndex()]?.hex;
436
331
  var _el$ = _tmpl$(), _el$2 = _el$.firstChild, _el$3 = _el$2.firstChild, _el$4 = _el$3.firstChild;
437
- var _ref$ = containerRef;
438
- "function" == typeof _ref$ || Array.isArray(_ref$) ? ref(()=>_ref$, _el$) : containerRef = _el$;
439
- spread(_el$, mergeProps(()=>({
332
+ spread(_el$, mergeProps({
333
+ get id () {
334
+ return p.id;
335
+ }
336
+ }, ()=>({
440
337
  class: twMerge(CLASSES.base, clsx({
441
338
  [CLASSES.flag.disabled]: context.disabled()
442
339
  }), p.class)
443
340
  }), {
444
- onMouseMove: handlePointerMove,
445
- onMouseLeave: handlePointerLeave,
446
341
  "data-slot": "color-wheel-flower",
447
342
  get ["data-color-mode"] () {
448
343
  return mode();
@@ -460,7 +355,11 @@ const __solidLayoutColorWheelFlower = (_stable, p)=>{
460
355
  spread(_el$4, mergeProps(()=>({
461
356
  class: twMerge(CLASSES.ring.base, CLASSES.ring.inner)
462
357
  })), false);
463
- insert(_el$, createComponent(color_swatch_picker, mergeProps(()=>({
358
+ insert(_el$, createComponent(color_swatch_picker, mergeProps({
359
+ get id () {
360
+ return memo(()=>!!p.id)() ? `${p.id}-palette` : void 0;
361
+ }
362
+ }, ()=>({
464
363
  class: CLASSES.picker
465
364
  }), {
466
365
  get value () {
@@ -477,112 +376,10 @@ const __solidLayoutColorWheelFlower = (_stable, p)=>{
477
376
  return colors();
478
377
  },
479
378
  children: (item, index)=>{
480
- let motionRef;
481
- let dotControl = null;
482
- let hasPaintedFinalState = false;
483
- const isHovered = ()=>hoveredIndex() === index();
484
- const isPressed = ()=>pressedIndex() === index();
485
379
  const isPulsing = ()=>pulseState()?.index === index();
486
- const dotBaseTarget = createMemo(()=>{
487
- if (context.disabled()) return {
488
- opacity: 0.5,
489
- scale: 1,
490
- x: 0,
491
- y: 0
492
- };
493
- const pointerState = pointer();
494
- const anchorIdx = hoveredIndex();
495
- let scale = 1;
496
- let offsetX = 0;
497
- let offsetY = 0;
498
- if (null !== anchorIdx && pointerState.active) {
499
- const anchor = colors()[anchorIdx];
500
- const distance = Math.sqrt((item.offsetX - anchor.offsetX) ** 2 + (item.offsetY - anchor.offsetY) ** 2);
501
- const waveRadius = 0.9 * MAX_RADIUS;
502
- const influence = Math.max(0, 1 - distance / waveRadius);
503
- if (influence > 0) {
504
- const maxDelta = 16;
505
- const deltaX = Math.max(-maxDelta, Math.min(maxDelta, pointerState.x - anchor.offsetX));
506
- const deltaY = Math.max(-maxDelta, Math.min(maxDelta, pointerState.y - anchor.offsetY));
507
- const waveStrength = isHovered() ? 0.25 : 0.18;
508
- offsetX += deltaX * influence * waveStrength;
509
- offsetY += deltaY * influence * waveStrength;
510
- const liftStrength = isHovered() ? 0.8 : 0.35;
511
- const lift = getLiftOffset(item, hoverLift * liftStrength);
512
- offsetX += lift.x * influence;
513
- offsetY += lift.y * influence;
514
- const scaleBoost = isHovered() ? 0.06 : 0.03;
515
- scale += influence * scaleBoost;
516
- }
517
- }
518
- return {
519
- opacity: 1,
520
- scale,
521
- x: offsetX,
522
- y: offsetY
523
- };
524
- });
525
- const dotTarget = createMemo(()=>{
526
- const base = dotBaseTarget();
527
- let scale = base.scale ?? 1;
528
- if (isPulsing()) scale *= pulseScale;
529
- if (isPressed()) scale *= pressScale;
530
- return {
531
- ...base,
532
- scale
533
- };
534
- });
535
- const glowOpacity = createMemo(()=>{
536
- if (context.disabled()) return 0;
537
- if (isHovered()) return 0.6;
538
- if (isPulsing()) return 0.35;
539
- return 0;
540
- });
541
- const dotTransition = ()=>{
542
- if (reduceMotion) return {
543
- duration: 0
544
- };
545
- const anchorIdx = hoveredIndex();
546
- const pointerState = pointer();
547
- let delay = 0;
548
- if (null !== anchorIdx && pointerState.active) {
549
- const anchor = colors()[anchorIdx];
550
- const distance = Math.sqrt((item.offsetX - anchor.offsetX) ** 2 + (item.offsetY - anchor.offsetY) ** 2);
551
- delay = Math.min(MAX_WAVE_DELAY, distance / MAX_WAVE_DISTANCE * MAX_WAVE_DELAY);
552
- }
553
- if (isPulsing()) return {
554
- duration: motionDurations.fast,
555
- easing: easeOutBack(1.25)
556
- };
557
- if (isHovered()) return {
558
- duration: motionDurations.fast,
559
- easing: motionEasings.out,
560
- delay
561
- };
562
- return {
563
- duration: motionDurations.base,
564
- easing: motionEasings.out,
565
- delay
566
- };
567
- };
568
- createTrackedEffect(()=>{
569
- if (!motionRef) return;
570
- const target = dotTarget();
571
- if (!hasPaintedFinalState) {
572
- applyMotionState(motionRef, target);
573
- hasPaintedFinalState = true;
574
- return;
575
- }
576
- const transition = dotTransition();
577
- dotControl?.stop();
578
- dotControl = runMotion(motionRef, readMotionState(motionRef), target, transition);
579
- });
580
- onCleanup(()=>{
581
- dotControl?.stop();
582
- });
583
380
  var _el$5 = _tmpl$2(), _el$6 = _el$5.firstChild, _el$7 = _el$6.firstChild, _el$8 = _el$7.firstChild, _el$9 = _el$8.nextSibling;
584
381
  spread(_el$5, mergeProps(()=>({
585
- class: CLASSES.dot.base
382
+ class: clsx(CLASSES.dot.base, isPulsing() && "color-wheel-flower__dot--pulsing")
586
383
  }), {
587
384
  get style () {
588
385
  return flowerPetalPosition(item.offsetX, item.offsetY);
@@ -591,9 +388,6 @@ const __solidLayoutColorWheelFlower = (_stable, p)=>{
591
388
  spread(_el$6, mergeProps(()=>({
592
389
  class: CLASSES.dot.frame
593
390
  })), true);
594
- ref(()=>(el)=>{
595
- motionRef = el;
596
- }, _el$7);
597
391
  spread(_el$7, mergeProps(()=>({
598
392
  class: CLASSES.dot.motion
599
393
  })), true);
@@ -602,13 +396,14 @@ const __solidLayoutColorWheelFlower = (_stable, p)=>{
602
396
  }), {
603
397
  get style () {
604
398
  return {
605
- opacity: glowOpacity(),
606
- "box-shadow": `0 0 8px ${toRgba(item.rgb, 0.3)}, 0 0 3px rgba(255,255,255,0.35)`,
607
- transition: reduceMotion ? "none" : "opacity 200ms ease-out, box-shadow 200ms ease-out"
399
+ "box-shadow": `0 0 8px ${toRgba(item.rgb, 0.3)}, 0 0 3px rgba(255,255,255,0.35)`
608
400
  };
609
401
  }
610
402
  }), false);
611
403
  insert(_el$7, createComponent(color_swatch, mergeProps({
404
+ get id () {
405
+ return memo(()=>!!p.id)() ? `${p.id}-petal-${index()}` : void 0;
406
+ },
612
407
  get color () {
613
408
  return item.hex;
614
409
  },
@@ -621,35 +416,17 @@ const __solidLayoutColorWheelFlower = (_stable, p)=>{
621
416
  },
622
417
  get state () {
623
418
  return context.disabled() ? "disabled" : void 0;
624
- },
625
- onMouseEnter: ()=>{
626
- if (!context.disabled()) setHoveredIndex(index());
627
- },
628
- onMouseLeave: ()=>{
629
- if (!context.disabled()) setHoveredIndex(null);
630
- },
631
- onFocus: ()=>{
632
- if (!context.disabled()) setHoveredIndex(index());
633
- },
634
- onBlur: ()=>{
635
- if (!context.disabled()) setHoveredIndex(null);
636
- },
637
- onPointerDown: ()=>{
638
- if (!context.disabled()) setPressedIndex(index());
639
- },
640
- onPointerUp: ()=>{
641
- if (!context.disabled()) setPressedIndex(null);
642
- },
643
- onPointerLeave: ()=>{
644
- if (!context.disabled()) setPressedIndex(null);
645
- },
646
- onPointerCancel: ()=>{
647
- if (!context.disabled()) setPressedIndex(null);
648
419
  }
649
420
  })), _el$9);
650
421
  spread(_el$9, mergeProps(()=>({
651
- class: clsx(CLASSES.highlight.base, isHovered() && CLASSES.highlight.hovered, isPulsing() && CLASSES.highlight.pulsing)
652
- })), false);
422
+ class: clsx(CLASSES.highlight.base, isPulsing() && CLASSES.highlight.pulsing)
423
+ }), {
424
+ get style () {
425
+ return {
426
+ "border-color": item.hex
427
+ };
428
+ }
429
+ }), false);
653
430
  return _el$5;
654
431
  }
655
432
  });
@@ -22,9 +22,11 @@ const sortItemsByDomOrder = (items)=>[
22
22
  });
23
23
  const __solidLayoutDropdownRoot = (_stable, p)=>{
24
24
  const others = omit(p, "children", "class", "open", "defaultOpen", "onOpenChange", "placement", "autoFlip", "disabled", "dataTheme", "ref");
25
- const baseId = createUniqueId();
26
- const triggerId = `${baseId}-trigger`;
27
- const menuId = `${baseId}-menu`;
25
+ const generatedBaseId = createUniqueId();
26
+ const authoredBaseId = "string" == typeof p.id ? p.id.trim() : "";
27
+ const baseId = authoredBaseId || generatedBaseId;
28
+ const triggerId = `${baseId}--trigger`;
29
+ const menuId = `${baseId}--menu`;
28
30
  const [internalOpen, setInternalOpen] = createSignal(Boolean(p.defaultOpen));
29
31
  const [items, setItems] = createSignal([]);
30
32
  const [focusedKey, setFocusedKey] = createSignal(void 0);
@@ -50,23 +50,27 @@ const __solidLayoutInlineEdit = (_stable, p)=>{
50
50
  effect(()=>({
51
51
  e: CLASSES.slot.read,
52
52
  t: CLASSES.slot.value,
53
- a: p.disabled,
54
- o: p.label,
55
- i: CLASSES.slot.trigger,
56
- n: CLASSES.slot.edit,
57
- s: p.value,
58
- h: p.label,
59
- r: twMerge(CLASSES.slot.field, p.fieldClass)
60
- }), ({ e, t, a, o, i, n, s, h, r }, _p$)=>{
53
+ a: p.id ? `${p.id}-trigger` : void 0,
54
+ o: p.disabled,
55
+ i: p.label,
56
+ n: CLASSES.slot.trigger,
57
+ s: CLASSES.slot.edit,
58
+ h: p.id ? `${p.id}-field` : void 0,
59
+ r: p.value,
60
+ d: p.label,
61
+ l: twMerge(CLASSES.slot.field, p.fieldClass)
62
+ }), ({ e, t, a, o, i, n, s, h, r, d, l }, _p$)=>{
61
63
  className(_el$2, e, _p$?.e);
62
64
  className(_el$3, t, _p$?.t);
63
- a !== _p$?.a && setAttribute(_el$4, "disabled", a);
64
- o !== _p$?.o && setAttribute(_el$4, "aria-label", o);
65
- className(_el$4, i, _p$?.i);
66
- className(_el$5, n, _p$?.n);
67
- _el$6.value = s ?? "";
68
- h !== _p$?.h && setAttribute(_el$6, "aria-label", h);
69
- className(_el$6, r, _p$?.r);
65
+ a !== _p$?.a && setAttribute(_el$4, "id", a);
66
+ o !== _p$?.o && setAttribute(_el$4, "disabled", o);
67
+ i !== _p$?.i && setAttribute(_el$4, "aria-label", i);
68
+ className(_el$4, n, _p$?.n);
69
+ className(_el$5, s, _p$?.s);
70
+ h !== _p$?.h && setAttribute(_el$6, "id", h);
71
+ _el$6.value = r ?? "";
72
+ d !== _p$?.d && setAttribute(_el$6, "aria-label", d);
73
+ className(_el$6, l, _p$?.l);
70
74
  });
71
75
  return _el$;
72
76
  };
@@ -1,9 +1,11 @@
1
1
  import type { Component as __LayoutComponent } from "solid-js";
2
2
  import "./LanguageSwitcher.css";
3
- import type { DropdownAlign } from "../dropdown";
3
+ import { type DropdownAlign } from "../dropdown";
4
4
  import type { UIBaseProps } from "../vocabulary";
5
5
  import type { I18nStore } from "./createI18n";
6
6
  export interface LanguageSwitcherProps extends UIBaseProps {
7
+ /** Stable identity for the language control. */
8
+ id?: string;
7
9
  /**
8
10
  * The i18n store to use for language state
9
11
  */
@@ -1,72 +1,120 @@
1
- import { createComponent, effect, insert, mergeProps, spread, template } from "@solidjs/web";
1
+ import { createComponent, insert, memo, mergeProps, spread, template } from "@solidjs/web";
2
2
  import { defineComponent } from "solid-layouts/solid-2/application-boundary";
3
3
  import "./LanguageSwitcher.css";
4
- import { For, omit } from "solid-js";
4
+ import { For, Show, createSignal, omit } from "solid-js";
5
5
  import { twMerge } from "../../lib/twMerge.js";
6
+ import dropdown from "../dropdown/index.js";
7
+ import icon from "../icon/index.js";
6
8
  import { CLASSES, componentRecipe } from "./LanguageSwitcher.recipe.js";
7
- var _tmpl$ = /*#__PURE__*/ template("<select>"), _tmpl$2 = /*#__PURE__*/ template("<option>");
9
+ var _tmpl$ = /*#__PURE__*/ template("<span>");
8
10
  const __solidLayoutLanguageSwitcher = (_stable, p)=>{
9
11
  const others = omit(p, "i18n", "class", "style", "aria-label", "currentLanguageLabel", "optionsLabel", "loadingLabel", "align", "onLanguageChange");
10
12
  const currentLanguageName = ()=>p.i18n.languageNames[p.i18n.locale];
13
+ const isSelected = (lang)=>p.i18n.locale === lang;
14
+ const [open, setOpen] = createSignal(false);
11
15
  const handleSelect = async (lang)=>{
12
16
  await p.i18n.setLocale(lang);
13
17
  p.onLanguageChange?.(lang);
14
18
  };
15
- const classes = ()=>twMerge(CLASSES.base, CLASSES.trigger, p.class);
16
- const move = (direction)=>{
17
- const languages = p.i18n.languages;
18
- const current = languages.findIndex((language)=>language.code === p.i18n.locale);
19
- const next = (Math.max(0, current) + direction + languages.length) % languages.length;
20
- const language = languages[next];
21
- if (language) handleSelect(language.code);
22
- };
23
- var _el$ = _tmpl$();
24
- spread(_el$, mergeProps(others, ()=>({
19
+ const classes = ()=>twMerge(CLASSES.base, p.class);
20
+ return createComponent(dropdown.Root, mergeProps(others, ()=>({
25
21
  class: classes()
26
22
  }), {
27
- get style () {
28
- return p.style;
29
- },
30
- get value () {
31
- return p.i18n.locale;
23
+ get open () {
24
+ return open();
32
25
  },
26
+ onOpenChange: setOpen,
33
27
  get disabled () {
34
28
  return p.i18n.isLoading;
35
29
  },
36
- get ["aria-busy"] () {
37
- return p.i18n.isLoading ? "true" : void 0;
38
- },
39
- get ["aria-label"] () {
40
- return `${p.currentLanguageLabel ?? "Current language"}: ${currentLanguageName()}`;
41
- },
42
- get title () {
43
- return p.optionsLabel ?? p["aria-label"] ?? "Language selector";
30
+ get style () {
31
+ return p.style;
44
32
  },
45
- onChange: (event)=>void handleSelect(event.currentTarget.value),
46
- onKeyDown: (event)=>{
47
- if ("ArrowDown" === event.key) {
48
- event.preventDefault();
49
- move(1);
50
- } else if ("ArrowUp" === event.key) {
51
- event.preventDefault();
52
- move(-1);
53
- }
33
+ get children () {
34
+ return [
35
+ createComponent(dropdown.Trigger, mergeProps(()=>({
36
+ class: CLASSES.trigger
37
+ }), {
38
+ get ["aria-busy"] () {
39
+ return p.i18n.isLoading ? "true" : void 0;
40
+ },
41
+ get ["aria-label"] () {
42
+ return `${p.currentLanguageLabel ?? "Current language"}: ${currentLanguageName()}`;
43
+ },
44
+ get title () {
45
+ return p.optionsLabel ?? p["aria-label"] ?? "Language selector";
46
+ },
47
+ get children () {
48
+ return createComponent(Show, {
49
+ get when () {
50
+ return !p.i18n.isLoading;
51
+ },
52
+ get fallback () {
53
+ return createComponent(icon, mergeProps({
54
+ src: "icon-[mdi--loading]"
55
+ }, ()=>({
56
+ class: CLASSES.loadingIcon
57
+ }), {
58
+ width: 16,
59
+ height: 16,
60
+ get ["aria-label"] () {
61
+ return p.loadingLabel ?? "Loading language";
62
+ }
63
+ }));
64
+ },
65
+ get children () {
66
+ var _el$ = _tmpl$();
67
+ spread(_el$, mergeProps({
68
+ "data-slot": "language-current"
69
+ }, ()=>({
70
+ class: CLASSES.locale
71
+ }), {
72
+ "aria-hidden": "true"
73
+ }), true);
74
+ insert(_el$, ()=>p.i18n.locale.toUpperCase());
75
+ return _el$;
76
+ }
77
+ });
78
+ }
79
+ })),
80
+ createComponent(dropdown.Menu, mergeProps(()=>({
81
+ class: CLASSES.menu
82
+ }), {
83
+ get align () {
84
+ return p.align;
85
+ },
86
+ get ["aria-label"] () {
87
+ return p.optionsLabel ?? "Language options";
88
+ },
89
+ get children () {
90
+ return createComponent(For, {
91
+ get each () {
92
+ return p.i18n.languages;
93
+ },
94
+ children: (lang)=>createComponent(dropdown.Item, mergeProps({
95
+ get id () {
96
+ return memo(()=>!!p.id)() ? `${p.id}-option-${lang.code}` : void 0;
97
+ },
98
+ onClick: ()=>void handleSelect(lang.code),
99
+ get ["aria-label"] () {
100
+ return lang.name;
101
+ }
102
+ }, ()=>({
103
+ class: twMerge(CLASSES.item, isSelected(lang.code) && CLASSES.itemSelected)
104
+ }), {
105
+ get ["aria-current"] () {
106
+ return isSelected(lang.code) ? "true" : void 0;
107
+ },
108
+ get children () {
109
+ return lang.name;
110
+ }
111
+ }))
112
+ });
113
+ }
114
+ }))
115
+ ];
54
116
  }
55
- }), true);
56
- insert(_el$, createComponent(For, {
57
- get each () {
58
- return p.i18n.languages;
59
- },
60
- children: (lang)=>(()=>{
61
- var _el$2 = _tmpl$2();
62
- insert(_el$2, ()=>lang.name);
63
- effect(()=>lang.code, (_v$)=>{
64
- _el$2.value = _v$;
65
- });
66
- return _el$2;
67
- })()
68
117
  }));
69
- return _el$;
70
118
  };
71
119
  const LanguageSwitcher = defineComponent({
72
120
  recipe: componentRecipe,
@@ -11,5 +11,6 @@ export declare const componentRecipe: import("solid-layouts/solid-2").Recipe<{
11
11
  readonly component: "language-switcher";
12
12
  readonly slots: {
13
13
  readonly root: {};
14
+ readonly "language-current": {};
14
15
  };
15
16
  }>;
@@ -11,18 +11,24 @@ const CLASSES = {
11
11
  const componentRecipe = recipe({
12
12
  component: "language-switcher",
13
13
  slots: {
14
- root: {}
14
+ root: {},
15
+ "language-current": {}
15
16
  },
16
17
  _layouts: {
17
18
  slots: {
18
19
  root: {
19
20
  base: "",
20
21
  axes: {}
22
+ },
23
+ "language-current": {
24
+ base: "",
25
+ axes: {}
21
26
  }
22
27
  },
23
28
  stateKeys: [],
24
29
  slotIds: {
25
- root: 0
30
+ root: 1,
31
+ "language-current": 0
26
32
  }
27
33
  }
28
34
  });
@@ -25,9 +25,7 @@ function createI18n(options) {
25
25
  if (lang === localeSignal() && Object.keys(translations()).length > 0) return;
26
26
  setIsLoading(true);
27
27
  try {
28
- const minDelay = new Promise((resolve)=>setTimeout(resolve, 100));
29
28
  let data;
30
- await minDelay;
31
29
  data = lang === defaultLanguage && Object.keys(initialTranslations).length > 0 ? initialTranslations : loadTranslations ? await loadTranslations(lang) : initialTranslations;
32
30
  setTranslations(data);
33
31
  setLocaleSignal(lang);