@g9tm/lynxcontrols 1.4.3 → 1.4.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/button/button.css +1 -0
  3. package/dist/button/button.css.map +1 -1
  4. package/dist/button/button.d.ts +2 -0
  5. package/dist/button/button.d.ts.map +1 -1
  6. package/dist/button/button.jsx +3 -2
  7. package/dist/button/button.jsx.map +1 -1
  8. package/dist/fields/index.d.ts +1 -1
  9. package/dist/fields/index.d.ts.map +1 -1
  10. package/dist/fields/index.jsx +1 -1
  11. package/dist/fields/outlined-field.d.ts +1 -1
  12. package/dist/fields/outlined-field.d.ts.map +1 -1
  13. package/dist/fields/outlined-field.jsx +13 -3
  14. package/dist/fields/outlined-field.jsx.map +1 -1
  15. package/dist/fields/use-text-input.d.ts +14 -1
  16. package/dist/fields/use-text-input.d.ts.map +1 -1
  17. package/dist/fields/use-text-input.jsx +19 -5
  18. package/dist/fields/use-text-input.jsx.map +1 -1
  19. package/dist/pickers/date-time-picker.d.ts.map +1 -1
  20. package/dist/pickers/date-time-picker.jsx +13 -4
  21. package/dist/pickers/date-time-picker.jsx.map +1 -1
  22. package/dist/pickers/picker-sheet.d.ts +5 -1
  23. package/dist/pickers/picker-sheet.d.ts.map +1 -1
  24. package/dist/pickers/picker-sheet.jsx +3 -17
  25. package/dist/pickers/picker-sheet.jsx.map +1 -1
  26. package/dist/pickers/pickers.css +32 -43
  27. package/dist/pickers/pickers.css.map +1 -1
  28. package/dist/pickers/wheel-column.d.ts +3 -1
  29. package/dist/pickers/wheel-column.d.ts.map +1 -1
  30. package/dist/pickers/wheel-column.jsx +17 -3
  31. package/dist/pickers/wheel-column.jsx.map +1 -1
  32. package/dist/popup/frame.d.ts +6 -0
  33. package/dist/popup/frame.d.ts.map +1 -1
  34. package/dist/popup/frame.jsx +8 -6
  35. package/dist/popup/frame.jsx.map +1 -1
  36. package/dist/popup/popup.css +23 -16
  37. package/dist/popup/popup.css.map +1 -1
  38. package/dist/popup/service.d.ts.map +1 -1
  39. package/dist/popup/service.jsx +3 -2
  40. package/dist/popup/service.jsx.map +1 -1
  41. package/dist/range-slider/range-slider.css +5 -0
  42. package/dist/range-slider/range-slider.css.map +1 -1
  43. package/dist/range-slider/range-slider.jsx +1 -1
  44. package/dist/range-slider/range-slider.jsx.map +1 -1
  45. package/dist/selection/selection-sheet.d.ts.map +1 -1
  46. package/dist/selection/selection-sheet.jsx +4 -2
  47. package/dist/selection/selection-sheet.jsx.map +1 -1
  48. package/dist/selection/selection.css +15 -0
  49. package/dist/selection/selection.css.map +1 -1
  50. package/dist/sheet/frame.d.ts.map +1 -1
  51. package/dist/sheet/frame.jsx +26 -19
  52. package/dist/sheet/frame.jsx.map +1 -1
  53. package/dist/sheet/options.d.ts +7 -0
  54. package/dist/sheet/options.d.ts.map +1 -1
  55. package/dist/sheet/options.jsx.map +1 -1
  56. package/dist/sheet/sheet.css +10 -0
  57. package/dist/sheet/sheet.css.map +1 -1
  58. package/dist/sheet/sizing.d.ts +1 -1
  59. package/dist/sheet/sizing.d.ts.map +1 -1
  60. package/dist/sheet/sizing.jsx +2 -2
  61. package/dist/sheet/sizing.jsx.map +1 -1
  62. package/dist/tabs/model.d.ts +1 -1
  63. package/dist/tabs/model.d.ts.map +1 -1
  64. package/dist/tabs/model.jsx.map +1 -1
  65. package/dist/tabs/tab-view.jsx +1 -1
  66. package/dist/tabs/tab-view.jsx.map +1 -1
  67. package/dist/toggle/chip-group.jsx +8 -2
  68. package/dist/toggle/chip-group.jsx.map +1 -1
  69. package/dist/toggle/switch.jsx +2 -1
  70. package/dist/toggle/switch.jsx.map +1 -1
  71. package/dist/toggle/toggle.css +5 -2
  72. package/dist/toggle/toggle.css.map +1 -1
  73. package/package.json +2 -2
@@ -1 +1 @@
1
- {"version":3,"file":"tabs/model.jsx","sources":["../../src/tabs/model.ts"],"sourcesContent":["import { formatNumber, type G9ImageSource, type G9NumberingSystem } from '@g9tm/lynxcontrols-foundation';\nimport type { ReactNode } from '@lynx-js/react';\nimport type { G9IconInput } from '../icon/icon';\n\n/** Visual treatment of the bar (MAUI `G9TabStyle`). */\nexport type G9TabStyle = 'underlined' | 'pill';\n/** Cell sizing (MAUI `G9TabMode`): equal full-width cells, or auto-width cells in a horizontal scroller. */\nexport type G9TabMode = 'fixed' | 'scrollable';\n/** Where the bar sits relative to the content (MAUI `G9TabBarPosition`). */\nexport type G9TabBarPosition = 'top' | 'bottom';\n\n/**\n * One tab (MAUI `G9TabItem`). A plain descriptor: change a field and re-render, and only that cell updates (MAUI\n * `VisualChanged` + in-place `UpdateCellContent`). Icon slot precedence as everywhere: emoji → icon → image path →\n * image source.\n */\nexport interface G9TabItem {\n /** Stable identity; keeps a realized body (and its state) with its tab across reorders. Default: the index. */\n readonly key?: string;\n readonly text?: string | null;\n readonly emoji?: string | null;\n readonly icon?: G9IconInput;\n readonly imagePath?: string | null;\n readonly image?: G9ImageSource | null;\n /** Inline pill badge with the formatted count; 0 = none. */\n readonly badgeCount?: number;\n /** Inline pill badge with custom text; wins over `badgeCount`. */\n readonly badgeText?: string | null;\n /** A 7×7 dot instead of a pill. */\n readonly badgeDot?: boolean;\n /** Badge fill. Default `var(--g9-error)`. */\n readonly badgeColor?: string | null;\n /** The body shown while this tab is active (MAUI `TabContent`); a function is called when the tab realizes. */\n readonly content?: ReactNode | (() => ReactNode);\n}\n\n/** Tab view metrics (MAUI `G9Metrics` tab constants and `G9TabView` private constants). */\nexport const g9TabViewMetrics = Object.freeze({\n tabHeight: 52,\n barInnerPadding: 4,\n barRadius: 26,\n pillVerticalInset: 2,\n pillRadius: 18,\n barToContentGap: 8,\n underlineThickness: 2.5,\n edgeLineThickness: 1,\n separatorVerticalInset: 12,\n indicatorMoveMs: 240,\n contentTransitionMs: 160,\n contentSlidePx: 6,\n lazyRealizeDelayMs: 240,\n contentPadding: Object.freeze([10, 10, 10, 0] as const),\n});\n\n/** The index actually shown: the selection clamped into the items (MAUI `EffectiveIndex`); -1 with no items. */\nexport function effectiveTabIndex(selectedIndex: number, count: number): number {\n if (count <= 0) return -1;\n if (!Number.isFinite(selectedIndex)) return 0;\n return Math.min(Math.max(Math.trunc(selectedIndex), 0), count - 1);\n}\n\n/** The identity of a tab: its `key`, else its index. */\nexport function tabKey(item: G9TabItem, index: number): string {\n return item.key ?? `#${index}`;\n}\n\n/** The inline badge of a tab: `null`, `'dot'`, or the pill text (custom text wins; counts are `N0`-grouped). */\nexport function tabBadge(item: G9TabItem, numberingSystem: G9NumberingSystem): 'dot' | string | null {\n if (item.badgeText != null && item.badgeText.trim() !== '') return item.badgeText;\n const count = item.badgeCount ?? 0;\n if (Number.isFinite(count) && count > 0) return formatNumber(Math.trunc(count), { numberingSystem });\n return item.badgeDot ? 'dot' : null;\n}\n\n/** Visual (left-to-right) order of the cells: reversed in RTL so the first tab sits at the reading start. */\nexport function tabVisualOrder(count: number, rtl: boolean): number[] {\n const order: number[] = [];\n for (let i = 0; i < count; i++) order.push(rtl ? count - 1 - i : i);\n return order;\n}\n\n/** Content slide start offset: forward arrives from the trailing edge, back from the leading edge; RTL mirrors. */\nexport function tabContentSlideFrom(previous: number, next: number, rtl: boolean): number {\n const forward = previous < 0 || next > previous;\n const sign = (forward ? 1 : -1) * (rtl ? -1 : 1);\n return g9TabViewMetrics.contentSlidePx * sign;\n}\n\n/** CSS padding from a MAUI-style thickness: one value, `[h, v]` or `[l, t, r, b]`. */\nexport function thicknessCss(value: number | readonly number[]): string {\n const parts = typeof value === 'number' ? [value] : value;\n const [l = 0, t = l, r = l, b = t] = parts.length === 2 ? [parts[0], parts[1], parts[0], parts[1]] : parts;\n return `${t}px ${r}px ${b}px ${l}px`;\n}\n\n/**\n * Lazy-once realization (MAUI \"Lazy tab-body rendering\"): a body is built on its first activation, after\n * `lazyRealizeDelayMs` (a spinner meanwhile), and then stays built, hidden while inactive, so its state survives. A\n * pending token makes rapid switches realize only the latest selection. `eager` builds everything up front.\n */\nexport class G9TabRealizer {\n private readonly realized = new Set<string>();\n private pending: string | null = null;\n private generation = 0;\n\n constructor(private readonly eager: () => boolean) {}\n\n isRealized(key: string): boolean {\n return this.eager() || this.realized.has(key);\n }\n\n /** Marks `key` active: returns `'shown'` when it is already built, else a token to pass to {@link realize}. */\n activate(key: string): 'shown' | number {\n if (this.isRealized(key)) {\n this.pending = null;\n return 'shown';\n }\n this.pending = key;\n this.generation += 1;\n return this.generation;\n }\n\n /** Realizes the pending key when `token` is still the latest activation; returns whether it did. */\n realize(token: number): boolean {\n if (token !== this.generation || this.pending === null) return false;\n this.realized.add(this.pending);\n this.pending = null;\n return true;\n }\n\n /** Drops keys that are no longer in the items (a removed tab's body is released). */\n retain(keys: readonly string[]): void {\n const live = new Set(keys);\n for (const key of Array.from(this.realized)) if (!live.has(key)) this.realized.delete(key);\n if (this.pending !== null && !live.has(this.pending)) this.pending = null;\n }\n\n get pendingKey(): string | null {\n return this.pending;\n }\n}\n"],"names":["g9TabViewMetrics","Object","effectiveTabIndex","selectedIndex","count","Number","Math","tabKey","item","index","_item_key","tabBadge","numberingSystem","_item_badgeCount","formatNumber","tabVisualOrder","rtl","order","i","tabContentSlideFrom","previous","next","forward","sign","thicknessCss","value","parts","l","t","r","b","G9TabRealizer","key","token","keys","live","Set","Array","eager"],"mappings":"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"}
1
+ {"version":3,"file":"tabs/model.jsx","sources":["../../src/tabs/model.ts"],"sourcesContent":["import { formatNumber, type G9ImageSource, type G9NumberingSystem } from '@g9tm/lynxcontrols-foundation';\nimport type { ReactNode } from '@lynx-js/react';\nimport type { G9IconInput } from '../icon/icon';\n\n/** Visual treatment of the bar (MAUI `G9TabStyle`). */\nexport type G9TabStyle = 'underlined' | 'pill';\n/** Cell sizing (MAUI `G9TabMode`): equal full-width cells, or auto-width cells in a horizontal scroller. */\nexport type G9TabMode = 'fixed' | 'scrollable';\n/** Where the bar sits relative to the content (MAUI `G9TabBarPosition`). */\nexport type G9TabBarPosition = 'top' | 'bottom';\n\n/**\n * One tab (MAUI `G9TabItem`). A plain descriptor: change a field and re-render, and only that cell updates (MAUI\n * `VisualChanged` + in-place `UpdateCellContent`). Icon slot precedence as everywhere: emoji → icon → image path →\n * image source.\n */\nexport interface G9TabItem {\n /** Stable identity; keeps a realized body (and its state) with its tab across reorders. Default: the index. */\n readonly key?: string;\n readonly text?: string | null;\n readonly emoji?: string | null;\n readonly icon?: G9IconInput;\n readonly imagePath?: string | null;\n readonly image?: G9ImageSource | null;\n /** Inline pill badge with the formatted count; 0 = none. */\n readonly badgeCount?: number;\n /** Inline pill badge with custom text; wins over `badgeCount`. */\n readonly badgeText?: string | null;\n /** A 7×7 dot instead of a pill. */\n readonly badgeDot?: boolean;\n /** Badge fill. Default `var(--g9-primary)` for the pill, `var(--g9-error)` for the dot (MAUI CreateBadge). */\n readonly badgeColor?: string | null;\n /** The body shown while this tab is active (MAUI `TabContent`); a function is called when the tab realizes. */\n readonly content?: ReactNode | (() => ReactNode);\n}\n\n/** Tab view metrics (MAUI `G9Metrics` tab constants and `G9TabView` private constants). */\nexport const g9TabViewMetrics = Object.freeze({\n tabHeight: 52,\n barInnerPadding: 4,\n barRadius: 26,\n pillVerticalInset: 2,\n pillRadius: 18,\n barToContentGap: 8,\n underlineThickness: 2.5,\n edgeLineThickness: 1,\n separatorVerticalInset: 12,\n indicatorMoveMs: 240,\n contentTransitionMs: 160,\n contentSlidePx: 6,\n lazyRealizeDelayMs: 240,\n contentPadding: Object.freeze([10, 10, 10, 0] as const),\n});\n\n/** The index actually shown: the selection clamped into the items (MAUI `EffectiveIndex`); -1 with no items. */\nexport function effectiveTabIndex(selectedIndex: number, count: number): number {\n if (count <= 0) return -1;\n if (!Number.isFinite(selectedIndex)) return 0;\n return Math.min(Math.max(Math.trunc(selectedIndex), 0), count - 1);\n}\n\n/** The identity of a tab: its `key`, else its index. */\nexport function tabKey(item: G9TabItem, index: number): string {\n return item.key ?? `#${index}`;\n}\n\n/** The inline badge of a tab: `null`, `'dot'`, or the pill text (custom text wins; counts are `N0`-grouped). */\nexport function tabBadge(item: G9TabItem, numberingSystem: G9NumberingSystem): 'dot' | string | null {\n if (item.badgeText != null && item.badgeText.trim() !== '') return item.badgeText;\n const count = item.badgeCount ?? 0;\n if (Number.isFinite(count) && count > 0) return formatNumber(Math.trunc(count), { numberingSystem });\n return item.badgeDot ? 'dot' : null;\n}\n\n/** Visual (left-to-right) order of the cells: reversed in RTL so the first tab sits at the reading start. */\nexport function tabVisualOrder(count: number, rtl: boolean): number[] {\n const order: number[] = [];\n for (let i = 0; i < count; i++) order.push(rtl ? count - 1 - i : i);\n return order;\n}\n\n/** Content slide start offset: forward arrives from the trailing edge, back from the leading edge; RTL mirrors. */\nexport function tabContentSlideFrom(previous: number, next: number, rtl: boolean): number {\n const forward = previous < 0 || next > previous;\n const sign = (forward ? 1 : -1) * (rtl ? -1 : 1);\n return g9TabViewMetrics.contentSlidePx * sign;\n}\n\n/** CSS padding from a MAUI-style thickness: one value, `[h, v]` or `[l, t, r, b]`. */\nexport function thicknessCss(value: number | readonly number[]): string {\n const parts = typeof value === 'number' ? [value] : value;\n const [l = 0, t = l, r = l, b = t] = parts.length === 2 ? [parts[0], parts[1], parts[0], parts[1]] : parts;\n return `${t}px ${r}px ${b}px ${l}px`;\n}\n\n/**\n * Lazy-once realization (MAUI \"Lazy tab-body rendering\"): a body is built on its first activation, after\n * `lazyRealizeDelayMs` (a spinner meanwhile), and then stays built, hidden while inactive, so its state survives. A\n * pending token makes rapid switches realize only the latest selection. `eager` builds everything up front.\n */\nexport class G9TabRealizer {\n private readonly realized = new Set<string>();\n private pending: string | null = null;\n private generation = 0;\n\n constructor(private readonly eager: () => boolean) {}\n\n isRealized(key: string): boolean {\n return this.eager() || this.realized.has(key);\n }\n\n /** Marks `key` active: returns `'shown'` when it is already built, else a token to pass to {@link realize}. */\n activate(key: string): 'shown' | number {\n if (this.isRealized(key)) {\n this.pending = null;\n return 'shown';\n }\n this.pending = key;\n this.generation += 1;\n return this.generation;\n }\n\n /** Realizes the pending key when `token` is still the latest activation; returns whether it did. */\n realize(token: number): boolean {\n if (token !== this.generation || this.pending === null) return false;\n this.realized.add(this.pending);\n this.pending = null;\n return true;\n }\n\n /** Drops keys that are no longer in the items (a removed tab's body is released). */\n retain(keys: readonly string[]): void {\n const live = new Set(keys);\n for (const key of Array.from(this.realized)) if (!live.has(key)) this.realized.delete(key);\n if (this.pending !== null && !live.has(this.pending)) this.pending = null;\n }\n\n get pendingKey(): string | null {\n return this.pending;\n }\n}\n"],"names":["g9TabViewMetrics","Object","effectiveTabIndex","selectedIndex","count","Number","Math","tabKey","item","index","_item_key","tabBadge","numberingSystem","_item_badgeCount","formatNumber","tabVisualOrder","rtl","order","i","tabContentSlideFrom","previous","next","forward","sign","thicknessCss","value","parts","l","t","r","b","G9TabRealizer","key","token","keys","live","Set","Array","eager"],"mappings":"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"}
@@ -192,7 +192,7 @@ function TabBarStrip(props) {
192
192
  {'dot' === badge ? <view className="g9-tabs__badge-dot" style={{
193
193
  backgroundColor: null != (_item_badgeColor = item.badgeColor) ? _item_badgeColor : 'var(--g9-error)'
194
194
  }}/> : null !== badge ? <view className="g9-tabs__badge" style={{
195
- backgroundColor: null != (_item_badgeColor1 = item.badgeColor) ? _item_badgeColor1 : 'var(--g9-error)'
195
+ backgroundColor: null != (_item_badgeColor1 = item.badgeColor) ? _item_badgeColor1 : 'var(--g9-primary)'
196
196
  }}>
197
197
  <text className="g9-tabs__badge-text">{badge}</text>
198
198
  </view> : null}
@@ -1 +1 @@
1
- {"version":3,"file":"tabs/tab-view.jsx","sources":["../../src/tabs/tab-view.tsx"],"sourcesContent":["import './tabs.css';\nimport { ViewPager, type ViewPagerRef } from '@lynx-js/lynx-ui-view-pager';\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from '@lynx-js/react';\nimport { g9RowStyle } from '../base/control';\nimport { startTimer, stopTimer } from '../base/timers';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { G9ActivityIndicator } from '../display/activity-indicator';\nimport { type G9NodeRef, invokeNodeWhenReady } from '../fields/use-text-input';\nimport { G9IconSlot } from '../icon/slot';\nimport { useG9Culture, useG9Direction } from '../provider/hooks';\nimport {\n effectiveTabIndex,\n type G9TabBarPosition,\n type G9TabItem,\n type G9TabMode,\n G9TabRealizer,\n type G9TabStyle,\n g9TabViewMetrics,\n tabBadge,\n tabContentSlideFrom,\n tabKey,\n tabVisualOrder,\n thicknessCss,\n} from './model';\n\n/** Props of {@link G9TabView}. */\nexport interface G9TabViewProps {\n /** The tabs (MAUI `Items`). Add, remove or reorder freely; give tabs a `key` so their bodies follow them. */\n readonly items: readonly G9TabItem[];\n /** Controlled selection (MAUI `SelectedIndex`, two-way). Out-of-range values show the nearest tab. */\n readonly selectedIndex?: number;\n /** Initial selection while uncontrolled. Default 0. */\n readonly defaultSelectedIndex?: number;\n /** A tab was chosen by a tap or a swipe (MAUI `SelectionChanged`). */\n readonly onSelectionChange?: (index: number) => void;\n /** Bar height (MAUI `TabHeight`). Default 52. */\n readonly tabHeight?: number;\n /** Bar background (MAUI `TabBarBackground`). Default transparent (underlined) / surface-container-low (pill). */\n readonly tabBarBackground?: string | null;\n /** Underline colour (underlined) or active text colour (pill) (MAUI `IndicatorColor`). Default primary. */\n readonly indicatorColor?: string | null;\n /** `'fixed'` (default): equal full-width cells. `'scrollable'`: auto-width cells that scroll. */\n readonly mode?: G9TabMode;\n /** `'top'` (default) or `'bottom'`. */\n readonly barPosition?: G9TabBarPosition;\n /** `'underlined'` (default) or `'pill'` (MAUI `Style`). */\n readonly tabStyle?: G9TabStyle;\n /** Only the bar: no content panel; drive your own host from `onSelectionChange` (MAUI `HeaderOnly`). */\n readonly headerOnly?: boolean;\n /** Border and rounded corners around the content (MAUI `ShowFrame`). Default false. */\n readonly showFrame?: boolean;\n /** Content border radius when `showFrame` (MAUI `FrameCornerRadius`). Default 0. */\n readonly frameCornerRadius?: number;\n /** Inset around the active body (MAUI `ContentPadding`): one value, `[h, v]` or `[l, t, r, b]`. Default 10,10,10,0. */\n readonly contentPadding?: number | readonly number[];\n /** Build every body up front instead of lazily on first activation (MAUI `EagerContent`). Default false. */\n readonly eagerContent?: boolean;\n /** Swipe between bodies (lynx-ui ViewPager). A Lynx addition; default false, as in MAUI. */\n readonly swipeEnabled?: boolean;\n readonly className?: string;\n}\n\n/**\n * Tabs with a bar and lazily realized bodies (MAUI `G9TabView`). Underlined (default) or pill style, fixed or\n * scrollable cells, bar on top or bottom, header-only; the indicator slides between cells; bodies are built on first\n * activation (spinner, then {@link g9TabViewMetrics} `lazyRealizeDelayMs`) and kept, hidden, so scroll and form state\n * survive; RTL reverses the cell order. With `swipeEnabled` the bodies sit in a lynx-ui ViewPager.\n */\nexport function G9TabView(props: G9TabViewProps): ReactNode {\n const items = props.items;\n const tabStyle = props.tabStyle ?? 'underlined';\n const mode = props.mode ?? 'fixed';\n const barPosition = props.barPosition ?? 'top';\n const tabHeight = props.tabHeight ?? g9TabViewMetrics.tabHeight;\n const rtl = useG9Direction() === 'rtl';\n const culture = useG9Culture();\n const [selected, setSelected] = useControllableState<number>({\n value: props.selectedIndex,\n defaultValue: props.defaultSelectedIndex ?? 0,\n onChange: props.onSelectionChange,\n name: 'G9TabView.selectedIndex',\n });\n const count = items.length;\n const effective = effectiveTabIndex(selected, count);\n const keys = items.map((item, i) => tabKey(item, i));\n const activeKey = effective >= 0 ? (keys[effective] as string) : null;\n\n const eager = props.eagerContent === true;\n const eagerRef = useRef(eager);\n eagerRef.current = eager;\n const realizer = useMemo(() => new G9TabRealizer(() => eagerRef.current), []);\n realizer.retain(keys);\n const [, setVersion] = useState(0);\n const [pending, setPending] = useState<string | null>(null);\n\n // Lazy-once realization of the active body; rapid switches realize only the latest.\n useEffect(() => {\n if (activeKey === null || props.headerOnly) {\n setPending(null);\n return;\n }\n const token = realizer.activate(activeKey);\n if (token === 'shown') {\n setPending(null);\n return;\n }\n setPending(activeKey);\n const t = startTimer(() => {\n if (realizer.realize(token)) {\n setPending(null);\n setVersion((v) => v + 1);\n }\n }, g9TabViewMetrics.lazyRealizeDelayMs);\n return () => stopTimer(t);\n }, [activeKey, props.headerOnly]);\n\n // Directional reveal of the newly active body (6 px slide + fade, 160 ms CubicOut).\n const previous = useRef(-1);\n const [reveal, setReveal] = useState<{ key: string | null; from: number; settled: boolean }>({\n key: activeKey,\n from: 0,\n settled: true,\n });\n useEffect(() => {\n const prev = previous.current;\n previous.current = effective;\n if (prev === effective || prev < 0) return;\n setReveal({ key: activeKey, from: tabContentSlideFrom(prev, effective, rtl), settled: false });\n const t = startTimer(() => setReveal((r) => ({ ...r, settled: true })), 16);\n return () => stopTimer(t);\n }, [effective]);\n\n const select = (index: number) => {\n if (index !== effective) setSelected(index);\n };\n\n const pager = useRef<ViewPagerRef | null>(null);\n const swipe = props.swipeEnabled === true && !props.headerOnly;\n const order = tabVisualOrder(count, rtl);\n const visualIndex = order.indexOf(effective);\n useEffect(() => {\n if (!swipe || visualIndex < 0) return;\n try {\n pager.current?.scrollToPage(visualIndex, true);\n } catch {\n // The pager is gone (unmounted mid-switch).\n }\n }, [visualIndex, swipe]);\n\n const bar = (\n <TabBarStrip\n items={items}\n order={order}\n effective={effective}\n tabStyle={tabStyle}\n mode={mode}\n tabHeight={tabHeight}\n background={props.tabBarBackground ?? null}\n indicatorColor={props.indicatorColor ?? null}\n numbering={culture.numberingSystem}\n onSelect={select}\n />\n );\n\n const bodyOf = (index: number): ReactNode => {\n const item = items[index] as G9TabItem;\n const key = keys[index] as string;\n const active = index === effective;\n if (!realizer.isRealized(key)) {\n return active && pending === key ? <Spinner /> : null;\n }\n const revealing = active && reveal.key === key && !reveal.settled;\n const style = {\n display: (active || swipe ? 'flex' : 'none') as 'flex' | 'none',\n transform: `translateX(${revealing ? reveal.from : 0}px)`,\n opacity: revealing ? 0 : 1,\n transition:\n revealing || swipe\n ? 'none'\n : `transform ${g9TabViewMetrics.contentTransitionMs}ms ease-out, opacity ${g9TabViewMetrics.contentTransitionMs}ms ease-out`,\n };\n const content = typeof item.content === 'function' ? (item.content as () => ReactNode)() : item.content;\n return (\n <view key={key} className={`g9-tabs__panel${active ? ' g9-tabs__panel--active' : ''}`} style={style}>\n {content}\n </view>\n );\n };\n\n const frame = props.showFrame\n ? {\n borderWidth: '1px',\n borderStyle: 'solid',\n borderColor: 'var(--g9-outline-variant)',\n borderRadius: `${props.frameCornerRadius ?? 0}px`,\n }\n : {};\n const content = props.headerOnly ? null : (\n <view\n className=\"g9-tabs__content\"\n style={{ padding: thicknessCss(props.contentPadding ?? g9TabViewMetrics.contentPadding), ...frame }}\n >\n {swipe ? (\n <ViewPager\n ref={pager}\n className=\"g9-tabs__pager\"\n data={order}\n getItemKey={(index: number) => keys[index] as string}\n initialSelectIndex={Math.max(visualIndex, 0)}\n onPageChange={(event) => {\n const next = order[Number(event.detail.index)];\n if (next !== undefined) select(next);\n }}\n >\n {(index: number) => <view className=\"g9-tabs__page\">{bodyOf(index)}</view>}\n </ViewPager>\n ) : (\n <>\n {items.map((_, i) => bodyOf(i))}\n {pending !== null && pending === activeKey ? <Spinner /> : null}\n </>\n )}\n </view>\n );\n\n return (\n <view\n className={`g9-tabs g9-tabs--${tabStyle} g9-tabs--${barPosition}${props.headerOnly ? ' g9-tabs--header-only' : ''} ${props.className ?? ''}`}\n >\n {barPosition === 'bottom' ? content : null}\n {bar}\n {barPosition === 'top' ? content : null}\n </view>\n );\n}\n\nfunction Spinner(): ReactNode {\n return (\n <view className=\"g9-tabs__spinner\">\n <G9ActivityIndicator running size={24} />\n </view>\n );\n}\n\ninterface StripProps {\n readonly items: readonly G9TabItem[];\n readonly order: readonly number[];\n readonly effective: number;\n readonly tabStyle: G9TabStyle;\n readonly mode: G9TabMode;\n readonly tabHeight: number;\n readonly background: string | null;\n readonly indicatorColor: string | null;\n readonly numbering: Parameters<typeof tabBadge>[1];\n readonly onSelect: (index: number) => void;\n}\n\nfunction TabBarStrip(props: StripProps): ReactNode {\n const { items, order, effective, tabStyle, mode } = props;\n const count = order.length;\n const pill = tabStyle === 'pill';\n const direction = useG9Direction();\n const indicator = props.indicatorColor ?? 'var(--g9-primary)';\n const fixed = mode === 'fixed';\n const cellRefs = useRef<Array<G9NodeRef | null>>([]);\n useEffect(() => {\n if (fixed || effective < 0) return;\n invokeNodeWhenReady({ current: cellRefs.current[effective] ?? null }, 'scrollIntoView', {\n scrollIntoViewOptions: { behavior: 'smooth', block: 'center', inline: 'center' },\n });\n }, [effective, fixed]);\n\n const cells = order.map((index, position) => {\n const item = items[index] as G9TabItem;\n const active = index === effective;\n const badge = tabBadge(item, props.numbering);\n const textColor = active\n ? pill\n ? (props.indicatorColor ?? 'var(--g9-on-primary-container)')\n : 'var(--g9-on-surface)'\n : 'var(--g9-on-surface-variant)';\n return (\n <view\n key={tabKey(item, index)}\n ref={(node: G9NodeRef | null) => {\n cellRefs.current[index] = node;\n }}\n className={`g9-tabs__cell${active ? ' g9-tabs__cell--active' : ''}`}\n style={fixed ? { flex: '1' } : {}}\n accessibility-element\n accessibility-traits=\"button\"\n accessibility-label={item.text ?? ''}\n bindtap={() => props.onSelect(index)}\n >\n {/* Sibling order is paint order in Lynx: the active pill goes first, behind the label. */}\n {!fixed && active ? (\n <view\n className={pill ? 'g9-tabs__cell-pill' : 'g9-tabs__cell-underline'}\n style={pill ? {} : { backgroundColor: indicator }}\n />\n ) : null}\n {position > 0 && !pill ? <view className=\"g9-tabs__separator\" /> : null}\n <view className=\"g9-tabs__cell-row\" style={g9RowStyle(direction)}>\n <G9IconSlot\n emoji={item.emoji}\n icon={item.icon}\n imagePath={item.imagePath}\n image={item.image}\n size={18}\n color={textColor}\n />\n {item.text ? (\n <text className=\"g9-tabs__label\" style={{ color: textColor, fontWeight: active ? '600' : '400' }}>\n {item.text}\n </text>\n ) : null}\n {badge === 'dot' ? (\n <view className=\"g9-tabs__badge-dot\" style={{ backgroundColor: item.badgeColor ?? 'var(--g9-error)' }} />\n ) : badge !== null ? (\n <view className=\"g9-tabs__badge\" style={{ backgroundColor: item.badgeColor ?? 'var(--g9-error)' }}>\n <text className=\"g9-tabs__badge-text\">{badge}</text>\n </view>\n ) : null}\n </view>\n </view>\n );\n });\n\n const position = order.indexOf(effective);\n const slider =\n fixed && position >= 0 ? (\n <view\n className={pill ? 'g9-tabs__pill' : 'g9-tabs__underline'}\n style={{\n left: `${(position * 100) / count}%`,\n width: `${100 / count}%`,\n transition: `left ${g9TabViewMetrics.indicatorMoveMs}ms cubic-bezier(0.215, 0.61, 0.355, 1)`,\n }}\n >\n <view\n className={pill ? 'g9-tabs__pill-fill' : 'g9-tabs__underline-fill'}\n style={pill ? {} : { backgroundColor: indicator }}\n />\n </view>\n ) : null;\n\n const barStyle = {\n height: `${props.tabHeight}px`,\n backgroundColor: props.background ?? (pill ? 'var(--g9-surface-container-low)' : 'transparent'),\n };\n return (\n <view className=\"g9-tabs__bar\" style={barStyle}>\n {fixed ? (\n <view className=\"g9-tabs__cells\">\n {slider}\n {cells}\n </view>\n ) : (\n <scroll-view className=\"g9-tabs__scroller\" scroll-orientation=\"horizontal\">\n <view className=\"g9-tabs__cells g9-tabs__cells--scrollable\">{cells}</view>\n </scroll-view>\n )}\n </view>\n );\n}\n"],"names":["G9TabView","props","_props_tabStyle","_props_mode","_props_barPosition","_props_tabHeight","_props_defaultSelectedIndex","_props_tabBarBackground","_props_indicatorColor","_props_frameCornerRadius","_props_contentPadding","_props_className","items","tabStyle","mode","barPosition","tabHeight","g9TabViewMetrics","rtl","useG9Direction","culture","useG9Culture","selected","setSelected","useControllableState","count","effective","effectiveTabIndex","keys","item","i","tabKey","activeKey","eager","eagerRef","useRef","realizer","useMemo","G9TabRealizer","setVersion","useState","pending","setPending","useEffect","token","t","startTimer","v","stopTimer","previous","reveal","setReveal","prev","tabContentSlideFrom","r","select","index","pager","swipe","order","tabVisualOrder","visualIndex","_pager_current","bar","TabBarStrip","bodyOf","key","active","Spinner","revealing","style","content","view","frame","thicknessCss","ViewPager","Math","event","next","Number","undefined","_","G9ActivityIndicator","_props_background","pill","direction","indicator","fixed","cellRefs","_cellRefs_current_effective","invokeNodeWhenReady","cells","position","_item_text","_item_badgeColor","_item_badgeColor1","badge","tabBadge","textColor","node","g9RowStyle","G9IconSlot","text","slider","barStyle","scroll-view"],"mappings":"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"}
1
+ {"version":3,"file":"tabs/tab-view.jsx","sources":["../../src/tabs/tab-view.tsx"],"sourcesContent":["import './tabs.css';\nimport { ViewPager, type ViewPagerRef } from '@lynx-js/lynx-ui-view-pager';\nimport { type ReactNode, useEffect, useMemo, useRef, useState } from '@lynx-js/react';\nimport { g9RowStyle } from '../base/control';\nimport { startTimer, stopTimer } from '../base/timers';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { G9ActivityIndicator } from '../display/activity-indicator';\nimport { type G9NodeRef, invokeNodeWhenReady } from '../fields/use-text-input';\nimport { G9IconSlot } from '../icon/slot';\nimport { useG9Culture, useG9Direction } from '../provider/hooks';\nimport {\n effectiveTabIndex,\n type G9TabBarPosition,\n type G9TabItem,\n type G9TabMode,\n G9TabRealizer,\n type G9TabStyle,\n g9TabViewMetrics,\n tabBadge,\n tabContentSlideFrom,\n tabKey,\n tabVisualOrder,\n thicknessCss,\n} from './model';\n\n/** Props of {@link G9TabView}. */\nexport interface G9TabViewProps {\n /** The tabs (MAUI `Items`). Add, remove or reorder freely; give tabs a `key` so their bodies follow them. */\n readonly items: readonly G9TabItem[];\n /** Controlled selection (MAUI `SelectedIndex`, two-way). Out-of-range values show the nearest tab. */\n readonly selectedIndex?: number;\n /** Initial selection while uncontrolled. Default 0. */\n readonly defaultSelectedIndex?: number;\n /** A tab was chosen by a tap or a swipe (MAUI `SelectionChanged`). */\n readonly onSelectionChange?: (index: number) => void;\n /** Bar height (MAUI `TabHeight`). Default 52. */\n readonly tabHeight?: number;\n /** Bar background (MAUI `TabBarBackground`). Default transparent (underlined) / surface-container-low (pill). */\n readonly tabBarBackground?: string | null;\n /** Underline colour (underlined) or active text colour (pill) (MAUI `IndicatorColor`). Default primary. */\n readonly indicatorColor?: string | null;\n /** `'fixed'` (default): equal full-width cells. `'scrollable'`: auto-width cells that scroll. */\n readonly mode?: G9TabMode;\n /** `'top'` (default) or `'bottom'`. */\n readonly barPosition?: G9TabBarPosition;\n /** `'underlined'` (default) or `'pill'` (MAUI `Style`). */\n readonly tabStyle?: G9TabStyle;\n /** Only the bar: no content panel; drive your own host from `onSelectionChange` (MAUI `HeaderOnly`). */\n readonly headerOnly?: boolean;\n /** Border and rounded corners around the content (MAUI `ShowFrame`). Default false. */\n readonly showFrame?: boolean;\n /** Content border radius when `showFrame` (MAUI `FrameCornerRadius`). Default 0. */\n readonly frameCornerRadius?: number;\n /** Inset around the active body (MAUI `ContentPadding`): one value, `[h, v]` or `[l, t, r, b]`. Default 10,10,10,0. */\n readonly contentPadding?: number | readonly number[];\n /** Build every body up front instead of lazily on first activation (MAUI `EagerContent`). Default false. */\n readonly eagerContent?: boolean;\n /** Swipe between bodies (lynx-ui ViewPager). A Lynx addition; default false, as in MAUI. */\n readonly swipeEnabled?: boolean;\n readonly className?: string;\n}\n\n/**\n * Tabs with a bar and lazily realized bodies (MAUI `G9TabView`). Underlined (default) or pill style, fixed or\n * scrollable cells, bar on top or bottom, header-only; the indicator slides between cells; bodies are built on first\n * activation (spinner, then {@link g9TabViewMetrics} `lazyRealizeDelayMs`) and kept, hidden, so scroll and form state\n * survive; RTL reverses the cell order. With `swipeEnabled` the bodies sit in a lynx-ui ViewPager.\n */\nexport function G9TabView(props: G9TabViewProps): ReactNode {\n const items = props.items;\n const tabStyle = props.tabStyle ?? 'underlined';\n const mode = props.mode ?? 'fixed';\n const barPosition = props.barPosition ?? 'top';\n const tabHeight = props.tabHeight ?? g9TabViewMetrics.tabHeight;\n const rtl = useG9Direction() === 'rtl';\n const culture = useG9Culture();\n const [selected, setSelected] = useControllableState<number>({\n value: props.selectedIndex,\n defaultValue: props.defaultSelectedIndex ?? 0,\n onChange: props.onSelectionChange,\n name: 'G9TabView.selectedIndex',\n });\n const count = items.length;\n const effective = effectiveTabIndex(selected, count);\n const keys = items.map((item, i) => tabKey(item, i));\n const activeKey = effective >= 0 ? (keys[effective] as string) : null;\n\n const eager = props.eagerContent === true;\n const eagerRef = useRef(eager);\n eagerRef.current = eager;\n const realizer = useMemo(() => new G9TabRealizer(() => eagerRef.current), []);\n realizer.retain(keys);\n const [, setVersion] = useState(0);\n const [pending, setPending] = useState<string | null>(null);\n\n // Lazy-once realization of the active body; rapid switches realize only the latest.\n useEffect(() => {\n if (activeKey === null || props.headerOnly) {\n setPending(null);\n return;\n }\n const token = realizer.activate(activeKey);\n if (token === 'shown') {\n setPending(null);\n return;\n }\n setPending(activeKey);\n const t = startTimer(() => {\n if (realizer.realize(token)) {\n setPending(null);\n setVersion((v) => v + 1);\n }\n }, g9TabViewMetrics.lazyRealizeDelayMs);\n return () => stopTimer(t);\n }, [activeKey, props.headerOnly]);\n\n // Directional reveal of the newly active body (6 px slide + fade, 160 ms CubicOut).\n const previous = useRef(-1);\n const [reveal, setReveal] = useState<{ key: string | null; from: number; settled: boolean }>({\n key: activeKey,\n from: 0,\n settled: true,\n });\n useEffect(() => {\n const prev = previous.current;\n previous.current = effective;\n if (prev === effective || prev < 0) return;\n setReveal({ key: activeKey, from: tabContentSlideFrom(prev, effective, rtl), settled: false });\n const t = startTimer(() => setReveal((r) => ({ ...r, settled: true })), 16);\n return () => stopTimer(t);\n }, [effective]);\n\n const select = (index: number) => {\n if (index !== effective) setSelected(index);\n };\n\n const pager = useRef<ViewPagerRef | null>(null);\n const swipe = props.swipeEnabled === true && !props.headerOnly;\n const order = tabVisualOrder(count, rtl);\n const visualIndex = order.indexOf(effective);\n useEffect(() => {\n if (!swipe || visualIndex < 0) return;\n try {\n pager.current?.scrollToPage(visualIndex, true);\n } catch {\n // The pager is gone (unmounted mid-switch).\n }\n }, [visualIndex, swipe]);\n\n const bar = (\n <TabBarStrip\n items={items}\n order={order}\n effective={effective}\n tabStyle={tabStyle}\n mode={mode}\n tabHeight={tabHeight}\n background={props.tabBarBackground ?? null}\n indicatorColor={props.indicatorColor ?? null}\n numbering={culture.numberingSystem}\n onSelect={select}\n />\n );\n\n const bodyOf = (index: number): ReactNode => {\n const item = items[index] as G9TabItem;\n const key = keys[index] as string;\n const active = index === effective;\n if (!realizer.isRealized(key)) {\n return active && pending === key ? <Spinner /> : null;\n }\n const revealing = active && reveal.key === key && !reveal.settled;\n const style = {\n display: (active || swipe ? 'flex' : 'none') as 'flex' | 'none',\n transform: `translateX(${revealing ? reveal.from : 0}px)`,\n opacity: revealing ? 0 : 1,\n transition:\n revealing || swipe\n ? 'none'\n : `transform ${g9TabViewMetrics.contentTransitionMs}ms ease-out, opacity ${g9TabViewMetrics.contentTransitionMs}ms ease-out`,\n };\n const content = typeof item.content === 'function' ? (item.content as () => ReactNode)() : item.content;\n return (\n <view key={key} className={`g9-tabs__panel${active ? ' g9-tabs__panel--active' : ''}`} style={style}>\n {content}\n </view>\n );\n };\n\n const frame = props.showFrame\n ? {\n borderWidth: '1px',\n borderStyle: 'solid',\n borderColor: 'var(--g9-outline-variant)',\n borderRadius: `${props.frameCornerRadius ?? 0}px`,\n }\n : {};\n const content = props.headerOnly ? null : (\n <view\n className=\"g9-tabs__content\"\n style={{ padding: thicknessCss(props.contentPadding ?? g9TabViewMetrics.contentPadding), ...frame }}\n >\n {swipe ? (\n <ViewPager\n ref={pager}\n className=\"g9-tabs__pager\"\n data={order}\n getItemKey={(index: number) => keys[index] as string}\n initialSelectIndex={Math.max(visualIndex, 0)}\n onPageChange={(event) => {\n const next = order[Number(event.detail.index)];\n if (next !== undefined) select(next);\n }}\n >\n {(index: number) => <view className=\"g9-tabs__page\">{bodyOf(index)}</view>}\n </ViewPager>\n ) : (\n <>\n {items.map((_, i) => bodyOf(i))}\n {pending !== null && pending === activeKey ? <Spinner /> : null}\n </>\n )}\n </view>\n );\n\n return (\n <view\n className={`g9-tabs g9-tabs--${tabStyle} g9-tabs--${barPosition}${props.headerOnly ? ' g9-tabs--header-only' : ''} ${props.className ?? ''}`}\n >\n {barPosition === 'bottom' ? content : null}\n {bar}\n {barPosition === 'top' ? content : null}\n </view>\n );\n}\n\nfunction Spinner(): ReactNode {\n return (\n <view className=\"g9-tabs__spinner\">\n <G9ActivityIndicator running size={24} />\n </view>\n );\n}\n\ninterface StripProps {\n readonly items: readonly G9TabItem[];\n readonly order: readonly number[];\n readonly effective: number;\n readonly tabStyle: G9TabStyle;\n readonly mode: G9TabMode;\n readonly tabHeight: number;\n readonly background: string | null;\n readonly indicatorColor: string | null;\n readonly numbering: Parameters<typeof tabBadge>[1];\n readonly onSelect: (index: number) => void;\n}\n\nfunction TabBarStrip(props: StripProps): ReactNode {\n const { items, order, effective, tabStyle, mode } = props;\n const count = order.length;\n const pill = tabStyle === 'pill';\n const direction = useG9Direction();\n const indicator = props.indicatorColor ?? 'var(--g9-primary)';\n const fixed = mode === 'fixed';\n const cellRefs = useRef<Array<G9NodeRef | null>>([]);\n useEffect(() => {\n if (fixed || effective < 0) return;\n invokeNodeWhenReady({ current: cellRefs.current[effective] ?? null }, 'scrollIntoView', {\n scrollIntoViewOptions: { behavior: 'smooth', block: 'center', inline: 'center' },\n });\n }, [effective, fixed]);\n\n const cells = order.map((index, position) => {\n const item = items[index] as G9TabItem;\n const active = index === effective;\n const badge = tabBadge(item, props.numbering);\n const textColor = active\n ? pill\n ? (props.indicatorColor ?? 'var(--g9-on-primary-container)')\n : 'var(--g9-on-surface)'\n : 'var(--g9-on-surface-variant)';\n return (\n <view\n key={tabKey(item, index)}\n ref={(node: G9NodeRef | null) => {\n cellRefs.current[index] = node;\n }}\n className={`g9-tabs__cell${active ? ' g9-tabs__cell--active' : ''}`}\n style={fixed ? { flex: '1' } : {}}\n accessibility-element\n accessibility-traits=\"button\"\n accessibility-label={item.text ?? ''}\n bindtap={() => props.onSelect(index)}\n >\n {/* Sibling order is paint order in Lynx: the active pill goes first, behind the label. */}\n {!fixed && active ? (\n <view\n className={pill ? 'g9-tabs__cell-pill' : 'g9-tabs__cell-underline'}\n style={pill ? {} : { backgroundColor: indicator }}\n />\n ) : null}\n {position > 0 && !pill ? <view className=\"g9-tabs__separator\" /> : null}\n <view className=\"g9-tabs__cell-row\" style={g9RowStyle(direction)}>\n <G9IconSlot\n emoji={item.emoji}\n icon={item.icon}\n imagePath={item.imagePath}\n image={item.image}\n size={18}\n color={textColor}\n />\n {item.text ? (\n <text className=\"g9-tabs__label\" style={{ color: textColor, fontWeight: active ? '600' : '400' }}>\n {item.text}\n </text>\n ) : null}\n {badge === 'dot' ? (\n <view className=\"g9-tabs__badge-dot\" style={{ backgroundColor: item.badgeColor ?? 'var(--g9-error)' }} />\n ) : badge !== null ? (\n // MAUI CreateBadge: `badgeColor ?? palette.Primary` (only the dot defaults to Error).\n <view className=\"g9-tabs__badge\" style={{ backgroundColor: item.badgeColor ?? 'var(--g9-primary)' }}>\n <text className=\"g9-tabs__badge-text\">{badge}</text>\n </view>\n ) : null}\n </view>\n </view>\n );\n });\n\n const position = order.indexOf(effective);\n const slider =\n fixed && position >= 0 ? (\n <view\n className={pill ? 'g9-tabs__pill' : 'g9-tabs__underline'}\n style={{\n left: `${(position * 100) / count}%`,\n width: `${100 / count}%`,\n transition: `left ${g9TabViewMetrics.indicatorMoveMs}ms cubic-bezier(0.215, 0.61, 0.355, 1)`,\n }}\n >\n <view\n className={pill ? 'g9-tabs__pill-fill' : 'g9-tabs__underline-fill'}\n style={pill ? {} : { backgroundColor: indicator }}\n />\n </view>\n ) : null;\n\n const barStyle = {\n height: `${props.tabHeight}px`,\n backgroundColor: props.background ?? (pill ? 'var(--g9-surface-container-low)' : 'transparent'),\n };\n return (\n <view className=\"g9-tabs__bar\" style={barStyle}>\n {fixed ? (\n <view className=\"g9-tabs__cells\">\n {slider}\n {cells}\n </view>\n ) : (\n <scroll-view className=\"g9-tabs__scroller\" scroll-orientation=\"horizontal\">\n <view className=\"g9-tabs__cells g9-tabs__cells--scrollable\">{cells}</view>\n </scroll-view>\n )}\n </view>\n );\n}\n"],"names":["G9TabView","props","_props_tabStyle","_props_mode","_props_barPosition","_props_tabHeight","_props_defaultSelectedIndex","_props_tabBarBackground","_props_indicatorColor","_props_frameCornerRadius","_props_contentPadding","_props_className","items","tabStyle","mode","barPosition","tabHeight","g9TabViewMetrics","rtl","useG9Direction","culture","useG9Culture","selected","setSelected","useControllableState","count","effective","effectiveTabIndex","keys","item","i","tabKey","activeKey","eager","eagerRef","useRef","realizer","useMemo","G9TabRealizer","setVersion","useState","pending","setPending","useEffect","token","t","startTimer","v","stopTimer","previous","reveal","setReveal","prev","tabContentSlideFrom","r","select","index","pager","swipe","order","tabVisualOrder","visualIndex","_pager_current","bar","TabBarStrip","bodyOf","key","active","Spinner","revealing","style","content","view","frame","thicknessCss","ViewPager","Math","event","next","Number","undefined","_","G9ActivityIndicator","_props_background","pill","direction","indicator","fixed","cellRefs","_cellRefs_current_effective","invokeNodeWhenReady","cells","position","_item_text","_item_badgeColor","_item_badgeColor1","badge","tabBadge","textColor","node","g9RowStyle","G9IconSlot","text","slider","barStyle","scroll-view"],"mappings":"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"}
@@ -4,7 +4,7 @@ import { g9ChildId, g9IdProps, g9RowStyle, useG9Control } from "../base/control.
4
4
  import { useG9Press } from "../base/press.jsx";
5
5
  import { selectionKey } from "../base/selection-item.jsx";
6
6
  import { useControllableState } from "../base/use-controllable-state.jsx";
7
- import { G9IconSlot } from "../icon/slot.jsx";
7
+ import { G9IconSlot, hasIconSlot } from "../icon/slot.jsx";
8
8
  import { useG9Settings, useG9Strings, useG9Theme } from "../provider/hooks.jsx";
9
9
  const EMPTY = [];
10
10
  function G9ChipGroup(props) {
@@ -91,7 +91,13 @@ function Chip(props) {
91
91
  }} accessibility-element={true} accessibility-traits="button" accessibility-label={item.text} {...props.selected ? {
92
92
  'accessibility-value': props.selectedLabel
93
93
  } : {}} bindtap={press}>
94
- <G9IconSlot emoji={item.emoji} icon={item.icon} imagePath={item.iconPath} image={item.iconImage} size={props.iconSize} color={props.color}/>
94
+ {}
95
+ {hasIconSlot({
96
+ emoji: item.emoji,
97
+ icon: item.icon,
98
+ imagePath: item.iconPath,
99
+ image: item.iconImage
100
+ }) ? <G9IconSlot emoji={item.emoji} icon={item.icon} imagePath={item.iconPath} image={item.iconImage} size={props.iconSize} color={props.color}/> : null}
95
101
  <text className="g9-chip__text" style={{
96
102
  color: props.color
97
103
  }}>
@@ -1 +1 @@
1
- {"version":3,"file":"toggle/chip-group.jsx","sources":["../../src/toggle/chip-group.tsx"],"sourcesContent":["import './toggle.css';\nimport {\n buildSolidOrGradient,\n fillToCss,\n formatColor,\n type G9ChipGroupLayoutMode,\n type G9ChipGroupSelectionMode,\n G9Metrics,\n G9StringKey,\n tryParseColor,\n} from '@g9tm/lynxcontrols-foundation';\nimport type { ReactNode } from '@lynx-js/react';\nimport { type G9ControlBaseProps, g9ChildId, g9IdProps, g9RowStyle, useG9Control } from '../base/control';\nimport { useG9Press } from '../base/press';\nimport { type G9SelectionItem, selectionKey } from '../base/selection-item';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { G9IconSlot } from '../icon/slot';\nimport { useG9Settings, useG9Strings, useG9Theme } from '../provider/hooks';\n\n/** Props of {@link G9ChipGroup} (MAUI `G9ChipGroup`). */\nexport interface G9ChipGroupProps extends G9ControlBaseProps {\n /** One chip per item (MAUI `ItemsSource`). Selection is by `selectionKey(item)`, so replaced objects keep it. */\n readonly items: ReadonlyArray<G9SelectionItem>;\n /** Default `'multiSelection'`. */\n readonly selectionMode?: G9ChipGroupSelectionMode;\n /** Multi mode: controlled selected keys (MAUI `SelectedItems`). */\n readonly selectedKeys?: ReadonlyArray<string>;\n readonly defaultSelectedKeys?: ReadonlyArray<string>;\n readonly onSelectedKeysChange?: (keys: ReadonlyArray<string>) => void;\n /** Single mode: controlled selected key (MAUI `SelectedItem`); `null` = none. */\n readonly selectedKey?: string | null;\n readonly defaultSelectedKey?: string | null;\n readonly onSelectedKeyChange?: (key: string | null, item: G9SelectionItem | null) => void;\n /** Single mode: tapping the selected chip clears the selection. Default false. */\n readonly allowNullSelection?: boolean;\n /** Gap between chips. Default 6. */\n readonly itemSpacing?: number;\n /** Default 36. */\n readonly chipHeight?: number;\n /** Leading icon size. Default 16. */\n readonly iconSize?: number;\n /** Group-wide selected fill (an item's `selectedColor` wins). Default primary. */\n readonly selectedBackground?: string | null;\n /** Group-wide selected text colour. Default on-primary. */\n readonly selectedTextColor?: string | null;\n /** `'wrap'` (default) or one horizontally scrolling line. */\n readonly layoutMode?: G9ChipGroupLayoutMode;\n /** Default 9 (`G9LayoutMetrics.ControlCornerRadius`). */\n readonly chipCornerRadius?: number;\n /** Check mark at the trailing edge of selected chips. Default true. */\n readonly showSelectionCheckmark?: boolean;\n /**\n * After every user tap (MAUI `SelectionChanged`): single mode `[item]` or `[]` (also when the tap changed nothing),\n * multi mode the selected items.\n */\n readonly onSelectionChange?: (items: ReadonlyArray<G9SelectionItem>) => void;\n}\n\nconst EMPTY: ReadonlyArray<string> = [];\n\n/**\n * Chip group (MAUI `G9ChipGroup`): single or multi selection by item identity, wrap or single-line scroll, colour\n * transition (140 ms) and check mark (120 ms) in CSS, press pulse 0.94 on the main thread. Disabled items are dimmed\n * and ignore taps.\n */\nexport function G9ChipGroup(props: G9ChipGroupProps): ReactNode {\n const control = useG9Control(props, 'g9-chip-group');\n const palette = useG9Theme().palette;\n const glyphs = useG9Settings().glyphs;\n const strings = useG9Strings();\n const single = props.selectionMode === 'singleSelection';\n const [keys, setKeys] = useControllableState<ReadonlyArray<string>>({\n value: props.selectedKeys,\n defaultValue: props.defaultSelectedKeys ?? EMPTY,\n onChange: props.onSelectedKeysChange,\n name: 'G9ChipGroup.selectedKeys',\n });\n const [key, setKey] = useControllableState<string | null, [G9SelectionItem | null]>({\n value: props.selectedKey,\n defaultValue: props.defaultSelectedKey ?? null,\n onChange: props.onSelectedKeyChange,\n name: 'G9ChipGroup.selectedKey',\n });\n const isSelected = (item: G9SelectionItem) =>\n single ? key === selectionKey(item) : keys.includes(selectionKey(item));\n\n const tap = (item: G9SelectionItem) => {\n if (control.disabled || item.isEnabled === false) return;\n const k = selectionKey(item);\n if (single) {\n const next = key === k ? (props.allowNullSelection ? null : k) : k;\n setKey(next, next === null ? null : item);\n props.onSelectionChange?.(next === null ? [] : [item]);\n return;\n }\n const next = keys.includes(k) ? keys.filter((x) => x !== k) : [...keys, k];\n setKeys(next);\n props.onSelectionChange?.(props.items.filter((i) => next.includes(selectionKey(i))));\n };\n\n const height = props.chipHeight ?? G9Metrics.ChipHeight;\n const spacing = props.itemSpacing ?? G9Metrics.ChipSpacing;\n const iconSize = props.iconSize ?? G9Metrics.ChipIconSize;\n const radius = props.chipCornerRadius ?? 9;\n const checkmark = props.showSelectionCheckmark !== false;\n const chips = props.items.map((item) => {\n const selected = isSelected(item);\n const bg = item.selectedColor ?? props.selectedBackground ?? palette.Primary;\n const fg = item.selectedTextColor ?? props.selectedTextColor ?? palette.OnPrimary;\n const parsed = tryParseColor(bg);\n const background = selected ? (parsed ? fillToCss(buildSolidOrGradient(parsed, true)) : bg) : palette.Surface;\n const color = selected ? fg : palette.TextSecondary;\n return (\n <Chip\n key={selectionKey(item)}\n direction={control.direction}\n item={item}\n selected={selected}\n background={background}\n stroke={selected ? (parsed ? formatColor(parsed) : bg) : palette.OutlineVariant}\n color={color}\n height={height}\n spacing={spacing}\n iconSize={iconSize}\n radius={radius}\n checkmark={checkmark}\n checkIcon={glyphs.check}\n groupDisabled={control.disabled}\n selectedLabel={strings.get(G9StringKey.Selected)}\n onTap={tap}\n id={g9ChildId(props.id, selectionKey(item))}\n />\n );\n });\n const scroll = props.layoutMode === 'singleLineScroll';\n return scroll ? (\n <scroll-view\n className={`${control.className} g9-chip-group--scroll`}\n {...control.idProps}\n scroll-orientation=\"horizontal\"\n >\n <view className=\"g9-chip-group__line\" style={g9RowStyle(control.direction)}>\n {chips}\n </view>\n </scroll-view>\n ) : (\n <view\n className={`${control.className} g9-chip-group--wrap`}\n {...control.idProps}\n style={g9RowStyle(control.direction)}\n >\n {chips}\n </view>\n );\n}\n\ninterface ChipProps {\n readonly item: G9SelectionItem;\n readonly selected: boolean;\n readonly background: string;\n readonly stroke: string;\n readonly color: string;\n readonly height: number;\n readonly spacing: number;\n readonly iconSize: number;\n readonly radius: number;\n readonly checkmark: boolean;\n readonly checkIcon: Parameters<typeof G9IconSlot>[0]['icon'];\n readonly groupDisabled: boolean;\n readonly selectedLabel: string;\n readonly onTap: (item: G9SelectionItem) => void;\n readonly direction: 'ltr' | 'rtl';\n /** The chip's automation id (`${groupId}_${key}`). */\n readonly id: string | undefined;\n}\n\nfunction Chip(props: ChipProps): ReactNode {\n const { item } = props;\n const disabled = props.groupDisabled || item.isEnabled === false;\n const press = useG9Press(() => props.onTap(item), { blocked: disabled, source: 'G9ChipGroup', guardMs: 0 });\n return (\n <view\n className={`g9-chip${props.selected ? ' g9-chip--selected' : ''}${item.isEnabled === false ? ' g9-chip--disabled' : ''}`}\n {...g9IdProps(props.id)}\n style={{\n ...g9RowStyle(props.direction),\n height: `${props.height}px`,\n minHeight: `${props.height}px`,\n [props.direction === 'rtl' ? 'marginLeft' : 'marginRight']: `${props.spacing}px`,\n marginBottom: `${props.spacing}px`,\n borderRadius: `${props.radius}px`,\n background: props.background,\n borderColor: props.stroke,\n }}\n accessibility-element={true}\n accessibility-traits=\"button\"\n accessibility-label={item.text}\n {...(props.selected ? { 'accessibility-value': props.selectedLabel } : {})}\n bindtap={press}\n >\n <G9IconSlot\n emoji={item.emoji}\n icon={item.icon}\n imagePath={item.iconPath}\n image={item.iconImage}\n size={props.iconSize}\n color={props.color}\n />\n <text className=\"g9-chip__text\" style={{ color: props.color }}>\n {item.text}\n </text>\n {props.checkmark ? (\n <view className={`g9-chip__check${props.selected ? ' g9-chip__check--on' : ''}`}>\n <G9IconSlot icon={props.checkIcon} size={G9Metrics.ChipIconSize} color={props.color} />\n </view>\n ) : null}\n </view>\n );\n}\n"],"names":["EMPTY","G9ChipGroup","props","_props_defaultSelectedKeys","_props_defaultSelectedKey","_props_chipHeight","_props_itemSpacing","_props_iconSize","_props_chipCornerRadius","control","useG9Control","palette","useG9Theme","glyphs","useG9Settings","strings","useG9Strings","single","keys","setKeys","useControllableState","key","setKey","isSelected","item","selectionKey","tap","k","next","x","i","height","G9Metrics","spacing","iconSize","radius","checkmark","chips","_ref","_ref1","selected","bg","fg","parsed","tryParseColor","background","fillToCss","buildSolidOrGradient","color","Chip","formatColor","G9StringKey","g9ChildId","scroll","scroll-view","view","g9RowStyle","disabled","press","useG9Press","g9IdProps","G9IconSlot","text"],"mappings":"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"}
1
+ {"version":3,"file":"toggle/chip-group.jsx","sources":["../../src/toggle/chip-group.tsx"],"sourcesContent":["import './toggle.css';\nimport {\n buildSolidOrGradient,\n fillToCss,\n formatColor,\n type G9ChipGroupLayoutMode,\n type G9ChipGroupSelectionMode,\n G9Metrics,\n G9StringKey,\n tryParseColor,\n} from '@g9tm/lynxcontrols-foundation';\nimport type { ReactNode } from '@lynx-js/react';\nimport { type G9ControlBaseProps, g9ChildId, g9IdProps, g9RowStyle, useG9Control } from '../base/control';\nimport { useG9Press } from '../base/press';\nimport { type G9SelectionItem, selectionKey } from '../base/selection-item';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { G9IconSlot, hasIconSlot } from '../icon/slot';\nimport { useG9Settings, useG9Strings, useG9Theme } from '../provider/hooks';\n\n/** Props of {@link G9ChipGroup} (MAUI `G9ChipGroup`). */\nexport interface G9ChipGroupProps extends G9ControlBaseProps {\n /** One chip per item (MAUI `ItemsSource`). Selection is by `selectionKey(item)`, so replaced objects keep it. */\n readonly items: ReadonlyArray<G9SelectionItem>;\n /** Default `'multiSelection'`. */\n readonly selectionMode?: G9ChipGroupSelectionMode;\n /** Multi mode: controlled selected keys (MAUI `SelectedItems`). */\n readonly selectedKeys?: ReadonlyArray<string>;\n readonly defaultSelectedKeys?: ReadonlyArray<string>;\n readonly onSelectedKeysChange?: (keys: ReadonlyArray<string>) => void;\n /** Single mode: controlled selected key (MAUI `SelectedItem`); `null` = none. */\n readonly selectedKey?: string | null;\n readonly defaultSelectedKey?: string | null;\n readonly onSelectedKeyChange?: (key: string | null, item: G9SelectionItem | null) => void;\n /** Single mode: tapping the selected chip clears the selection. Default false. */\n readonly allowNullSelection?: boolean;\n /** Gap between chips. Default 6. */\n readonly itemSpacing?: number;\n /** Default 36. */\n readonly chipHeight?: number;\n /** Leading icon size. Default 16. */\n readonly iconSize?: number;\n /** Group-wide selected fill (an item's `selectedColor` wins). Default primary. */\n readonly selectedBackground?: string | null;\n /** Group-wide selected text colour. Default on-primary. */\n readonly selectedTextColor?: string | null;\n /** `'wrap'` (default) or one horizontally scrolling line. */\n readonly layoutMode?: G9ChipGroupLayoutMode;\n /** Default 9 (`G9LayoutMetrics.ControlCornerRadius`). */\n readonly chipCornerRadius?: number;\n /** Check mark at the trailing edge of selected chips. Default true. */\n readonly showSelectionCheckmark?: boolean;\n /**\n * After every user tap (MAUI `SelectionChanged`): single mode `[item]` or `[]` (also when the tap changed nothing),\n * multi mode the selected items.\n */\n readonly onSelectionChange?: (items: ReadonlyArray<G9SelectionItem>) => void;\n}\n\nconst EMPTY: ReadonlyArray<string> = [];\n\n/**\n * Chip group (MAUI `G9ChipGroup`): single or multi selection by item identity, wrap or single-line scroll, colour\n * transition (140 ms) and check mark (120 ms) in CSS, press pulse 0.94 on the main thread. Disabled items are dimmed\n * and ignore taps.\n */\nexport function G9ChipGroup(props: G9ChipGroupProps): ReactNode {\n const control = useG9Control(props, 'g9-chip-group');\n const palette = useG9Theme().palette;\n const glyphs = useG9Settings().glyphs;\n const strings = useG9Strings();\n const single = props.selectionMode === 'singleSelection';\n const [keys, setKeys] = useControllableState<ReadonlyArray<string>>({\n value: props.selectedKeys,\n defaultValue: props.defaultSelectedKeys ?? EMPTY,\n onChange: props.onSelectedKeysChange,\n name: 'G9ChipGroup.selectedKeys',\n });\n const [key, setKey] = useControllableState<string | null, [G9SelectionItem | null]>({\n value: props.selectedKey,\n defaultValue: props.defaultSelectedKey ?? null,\n onChange: props.onSelectedKeyChange,\n name: 'G9ChipGroup.selectedKey',\n });\n const isSelected = (item: G9SelectionItem) =>\n single ? key === selectionKey(item) : keys.includes(selectionKey(item));\n\n const tap = (item: G9SelectionItem) => {\n if (control.disabled || item.isEnabled === false) return;\n const k = selectionKey(item);\n if (single) {\n const next = key === k ? (props.allowNullSelection ? null : k) : k;\n setKey(next, next === null ? null : item);\n props.onSelectionChange?.(next === null ? [] : [item]);\n return;\n }\n const next = keys.includes(k) ? keys.filter((x) => x !== k) : [...keys, k];\n setKeys(next);\n props.onSelectionChange?.(props.items.filter((i) => next.includes(selectionKey(i))));\n };\n\n const height = props.chipHeight ?? G9Metrics.ChipHeight;\n const spacing = props.itemSpacing ?? G9Metrics.ChipSpacing;\n const iconSize = props.iconSize ?? G9Metrics.ChipIconSize;\n const radius = props.chipCornerRadius ?? 9;\n const checkmark = props.showSelectionCheckmark !== false;\n const chips = props.items.map((item) => {\n const selected = isSelected(item);\n const bg = item.selectedColor ?? props.selectedBackground ?? palette.Primary;\n const fg = item.selectedTextColor ?? props.selectedTextColor ?? palette.OnPrimary;\n const parsed = tryParseColor(bg);\n const background = selected ? (parsed ? fillToCss(buildSolidOrGradient(parsed, true)) : bg) : palette.Surface;\n const color = selected ? fg : palette.TextSecondary;\n return (\n <Chip\n key={selectionKey(item)}\n direction={control.direction}\n item={item}\n selected={selected}\n background={background}\n stroke={selected ? (parsed ? formatColor(parsed) : bg) : palette.OutlineVariant}\n color={color}\n height={height}\n spacing={spacing}\n iconSize={iconSize}\n radius={radius}\n checkmark={checkmark}\n checkIcon={glyphs.check}\n groupDisabled={control.disabled}\n selectedLabel={strings.get(G9StringKey.Selected)}\n onTap={tap}\n id={g9ChildId(props.id, selectionKey(item))}\n />\n );\n });\n const scroll = props.layoutMode === 'singleLineScroll';\n return scroll ? (\n <scroll-view\n className={`${control.className} g9-chip-group--scroll`}\n {...control.idProps}\n scroll-orientation=\"horizontal\"\n >\n <view className=\"g9-chip-group__line\" style={g9RowStyle(control.direction)}>\n {chips}\n </view>\n </scroll-view>\n ) : (\n <view\n className={`${control.className} g9-chip-group--wrap`}\n {...control.idProps}\n style={g9RowStyle(control.direction)}\n >\n {chips}\n </view>\n );\n}\n\ninterface ChipProps {\n readonly item: G9SelectionItem;\n readonly selected: boolean;\n readonly background: string;\n readonly stroke: string;\n readonly color: string;\n readonly height: number;\n readonly spacing: number;\n readonly iconSize: number;\n readonly radius: number;\n readonly checkmark: boolean;\n readonly checkIcon: Parameters<typeof G9IconSlot>[0]['icon'];\n readonly groupDisabled: boolean;\n readonly selectedLabel: string;\n readonly onTap: (item: G9SelectionItem) => void;\n readonly direction: 'ltr' | 'rtl';\n /** The chip's automation id (`${groupId}_${key}`). */\n readonly id: string | undefined;\n}\n\nfunction Chip(props: ChipProps): ReactNode {\n const { item } = props;\n const disabled = props.groupDisabled || item.isEnabled === false;\n const press = useG9Press(() => props.onTap(item), { blocked: disabled, source: 'G9ChipGroup', guardMs: 0 });\n return (\n <view\n className={`g9-chip${props.selected ? ' g9-chip--selected' : ''}${item.isEnabled === false ? ' g9-chip--disabled' : ''}`}\n {...g9IdProps(props.id)}\n style={{\n ...g9RowStyle(props.direction),\n height: `${props.height}px`,\n minHeight: `${props.height}px`,\n [props.direction === 'rtl' ? 'marginLeft' : 'marginRight']: `${props.spacing}px`,\n marginBottom: `${props.spacing}px`,\n borderRadius: `${props.radius}px`,\n background: props.background,\n borderColor: props.stroke,\n }}\n accessibility-element={true}\n accessibility-traits=\"button\"\n accessibility-label={item.text}\n {...(props.selected ? { 'accessibility-value': props.selectedLabel } : {})}\n bindtap={press}\n >\n {/* Only when the item has one (MAUI adds the icon view only then): an empty slot still took the row's 6 dp gap,\n and every icon-less chip came out 6 dp wider than MAUI's. */}\n {hasIconSlot({ emoji: item.emoji, icon: item.icon, imagePath: item.iconPath, image: item.iconImage }) ? (\n <G9IconSlot\n emoji={item.emoji}\n icon={item.icon}\n imagePath={item.iconPath}\n image={item.iconImage}\n size={props.iconSize}\n color={props.color}\n />\n ) : null}\n <text className=\"g9-chip__text\" style={{ color: props.color }}>\n {item.text}\n </text>\n {props.checkmark ? (\n <view className={`g9-chip__check${props.selected ? ' g9-chip__check--on' : ''}`}>\n <G9IconSlot icon={props.checkIcon} size={G9Metrics.ChipIconSize} color={props.color} />\n </view>\n ) : null}\n </view>\n );\n}\n"],"names":["EMPTY","G9ChipGroup","props","_props_defaultSelectedKeys","_props_defaultSelectedKey","_props_chipHeight","_props_itemSpacing","_props_iconSize","_props_chipCornerRadius","control","useG9Control","palette","useG9Theme","glyphs","useG9Settings","strings","useG9Strings","single","keys","setKeys","useControllableState","key","setKey","isSelected","item","selectionKey","tap","k","next","x","i","height","G9Metrics","spacing","iconSize","radius","checkmark","chips","_ref","_ref1","selected","bg","fg","parsed","tryParseColor","background","fillToCss","buildSolidOrGradient","color","Chip","formatColor","G9StringKey","g9ChildId","scroll","scroll-view","view","g9RowStyle","disabled","press","useG9Press","g9IdProps","hasIconSlot","G9IconSlot","text"],"mappings":"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"}
@@ -172,8 +172,9 @@ const switch_G9Switch = forwardRef(function(props, ref) {
172
172
  height: `${G9Metrics.SwitchHeight}px`,
173
173
  backgroundColor: track
174
174
  }}>
175
+ {}
175
176
  <view className="g9-switch__mark" style={{
176
- [rtl ? 'right' : 'left']: checked ? `${width - 15 - 6}px` : '12px'
177
+ [rtl ? 'right' : 'left']: checked ? '9px' : '12px'
177
178
  }}>
178
179
  {checked ? <text className="g9-switch__tick">✓</text> : <view className="g9-switch__dot"/>}
179
180
  </view>
@@ -1 +1 @@
1
- {"version":3,"file":"toggle/switch.jsx","sources":["../../src/toggle/switch.tsx"],"sourcesContent":["import './toggle.css';\nimport {\n formatColor,\n G9Metrics,\n G9StringKey,\n switchOffTrack,\n switchOnTrack,\n switchThumbOff,\n switchThumbOn,\n} from '@g9tm/lynxcontrols-foundation';\nimport {\n createContext,\n forwardRef,\n type ReactNode,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from '@lynx-js/react';\nimport { type G9ControlBaseProps, g9RowStyle, g9TextStart, useG9Control } from '../base/control';\nimport { useG9Press } from '../base/press';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { G9CoreContext } from '../provider/contexts';\nimport { useG9Strings, useG9Theme } from '../provider/hooks';\n\n// ---- selection groups (MAUI `SelectionGroup`: radio-style, scoped to the provider) -------------------------------\n\ninterface GroupMember {\n turnOff(): void;\n}\n\nconst registries = new WeakMap<object, Map<string, Set<GroupMember>>>();\nconst globalScope = {};\n\nfunction groupSet(scope: object, group: string): Set<GroupMember> {\n let groups = registries.get(scope);\n if (!groups) {\n groups = new Map();\n registries.set(scope, groups);\n }\n let set = groups.get(group);\n if (!set) {\n set = new Set();\n groups.set(group, set);\n }\n return set;\n}\n\n// ---- G9SwitchGroup ---------------------------------------------------------------------------------------------\n\ninterface SwitchGroupContextValue {\n readonly minOneActive: boolean;\n activeCount(): number;\n report(id: number, on: boolean | null): void;\n}\n\nconst SwitchGroupContext = createContext<SwitchGroupContextValue | null>(null);\n\n/** Props of {@link G9SwitchGroup} (MAUI `G9SwitchGroup`). */\nexport interface G9SwitchGroupProps extends G9ControlBaseProps {\n /** A tap cannot turn off the last active switch of the group (it shakes). Default false. */\n readonly minOneActive?: boolean;\n /** Shows `active / total` under the switches (warning colour at ≤ 1 with `minOneActive`). Default false. */\n readonly showLiveStatus?: boolean;\n /** Told when the number of active switches changes (MAUI `ActiveSwitchCount`). */\n readonly onActiveCountChange?: (active: number, total: number) => void;\n readonly children?: ReactNode;\n}\n\n/**\n * A vertical group of switches (MAUI `G9SwitchGroup`): counts its switches (nearest group only, as MAUI's direct\n * children), optionally keeps one on and shows a live `active / total` status. It does not make switches exclusive:\n * use `selectionGroup` for radio behaviour.\n */\nexport function G9SwitchGroup(props: G9SwitchGroupProps): ReactNode {\n const control = useG9Control(props, 'g9-switch-group');\n const [states, setStates] = useState<ReadonlyMap<number, boolean>>(() => new Map());\n const latest = useRef(states);\n latest.current = states;\n const minOneActive = props.minOneActive === true;\n const minRef = useRef(minOneActive);\n minRef.current = minOneActive;\n // One context object for the group's life: switches key their effects on it.\n const value = useRef<SwitchGroupContextValue | null>(null);\n if (value.current === null) {\n value.current = {\n get minOneActive() {\n return minRef.current;\n },\n activeCount: () => {\n let n = 0;\n for (const on of latest.current.values()) if (on) n++;\n return n;\n },\n report: (id, on) =>\n setStates((current) => {\n if (on === null ? !current.has(id) : current.get(id) === on) return current;\n const next = new Map(current);\n if (on === null) next.delete(id);\n else next.set(id, on);\n latest.current = next;\n return next;\n }),\n };\n }\n let active = 0;\n for (const on of states.values()) if (on) active++;\n const total = states.size;\n const notify = useRef(props.onActiveCountChange);\n notify.current = props.onActiveCountChange;\n useEffect(() => {\n notify.current?.(active, total);\n }, [active, total]);\n const warn = minOneActive && active <= 1;\n return (\n <SwitchGroupContext.Provider value={value.current}>\n <view className={control.className} {...control.idProps}>\n {props.children}\n {props.showLiveStatus ? (\n <text\n className=\"g9-switch-group__status\"\n style={{ color: warn ? 'var(--g9-warning)' : 'var(--g9-text-tertiary)' }}\n >\n {`${active} / ${total}`}\n </text>\n ) : null}\n </view>\n </SwitchGroupContext.Provider>\n );\n}\n\n// ---- G9Switch ----------------------------------------------------------------------------------------------------\n\n/** Props of {@link G9Switch} (MAUI `G9Switch`). */\nexport interface G9SwitchProps extends G9ControlBaseProps {\n /** Controlled state (MAUI `IsOn`). */\n readonly checked?: boolean;\n readonly defaultChecked?: boolean;\n /**\n * Once per change made by the switch: a tap, `toggle()`, or being turned off by its selection group (MAUI\n * `Toggled`). Never for a value the parent pushed in.\n */\n readonly onCheckedChange?: (checked: boolean) => void;\n /** A tap cannot turn it off (it shakes); code still can. Default false. */\n readonly isRequired?: boolean;\n /** Radio group name: turning this on turns off the others with the same name under the same provider. */\n readonly selectionGroup?: string | null;\n /** Form row: title/description fill the start, switch at the end, padded. Default false. */\n readonly isInFormRow?: boolean;\n /** Bold 14 title (form row only); the accessibility name. */\n readonly title?: string | null;\n /** 12 px description under the title (form row only). */\n readonly description?: string | null;\n}\n\n/** Imperative handle of {@link G9Switch}. */\nexport interface G9SwitchHandle {\n /** Same as a tap. */\n toggle(): void;\n}\n\nlet switchIds = 0;\n\n/**\n * Switch (MAUI `G9Switch`): 56 × 32 track, 24 px thumb that stretches while travelling, 240 ms spring-like CSS\n * transition, tick/dot track mark; RTL moves the \"on\" side to the left. A blocked tap (required, or the last active\n * switch of a `minOneActive` group) shakes instead of toggling. Disabled: opacity 0.45.\n */\nexport const G9Switch = forwardRef<G9SwitchHandle, G9SwitchProps>(function G9Switch(props, ref): ReactNode {\n const control = useG9Control(props, 'g9-switch');\n const theme = useG9Theme();\n const strings = useG9Strings();\n const core = useContext(G9CoreContext);\n const group = useContext(SwitchGroupContext);\n const [checked, setChecked] = useControllableState<boolean>({\n value: props.checked,\n defaultValue: props.defaultChecked ?? false,\n onChange: props.onCheckedChange,\n name: 'G9Switch.checked',\n });\n const [shake, setShake] = useState(0);\n const id = useRef(0);\n if (id.current === 0) id.current = ++switchIds;\n const latestChecked = useRef(checked);\n latestChecked.current = checked;\n const setRef = useRef(setChecked);\n setRef.current = setChecked;\n\n // Report to the group.\n useEffect(() => {\n group?.report(id.current, checked);\n }, [group, checked]);\n useEffect(() => () => group?.report(id.current, null), [group]);\n\n // Selection group registration (while mounted and named).\n const groupName = props.selectionGroup && props.selectionGroup.trim() !== '' ? props.selectionGroup : null;\n const scope: object = core ?? globalScope;\n const memberRef = useRef<GroupMember | null>(null);\n useEffect(() => {\n if (!groupName) return;\n const member: GroupMember = { turnOff: () => setRef.current(false) };\n const set = groupSet(scope, groupName);\n set.add(member);\n memberRef.current = member;\n return () => {\n set.delete(member);\n memberRef.current = null;\n };\n }, [groupName, scope]);\n useEffect(() => {\n if (!checked || !groupName) return;\n for (const other of groupSet(scope, groupName)) if (other !== memberRef.current) other.turnOff();\n }, [checked, groupName, scope]);\n\n const toggle = () => {\n if (control.disabled) return;\n const on = latestChecked.current;\n if (on && (props.isRequired || (group?.minOneActive && group.activeCount() <= 1))) {\n setShake((n) => n + 1);\n return;\n }\n setChecked(!on);\n };\n useImperativeHandle(ref, () => ({ toggle }));\n const press = useG9Press(toggle, { blocked: control.disabled, source: 'G9Switch', guardMs: 0 });\n\n const rtl = control.direction === 'rtl';\n const width = G9Metrics.SwitchWidth;\n const thumb = G9Metrics.SwitchThumb;\n const travel = width - 4 - thumb - 4;\n const x = (checked ? travel : 0) * (rtl ? -1 : 1);\n const track = formatColor(checked ? switchOnTrack(theme) : switchOffTrack(theme));\n const thumbColor = formatColor(checked ? switchThumbOn(theme) : switchThumbOff(theme));\n const form = props.isInFormRow === true;\n const title = props.title && props.title.trim() !== '' ? props.title : null;\n const description = props.description && props.description.trim() !== '' ? props.description : null;\n return (\n <view\n className={`${control.className}${form ? ' g9-switch--row' : ''}`}\n {...control.idProps}\n style={g9RowStyle(control.direction)}\n accessibility-element={true}\n accessibility-traits=\"button\"\n {...(checked ? { 'accessibility-value': strings.get(G9StringKey.Selected) } : {})}\n {...((props.accessibilityLabel ?? title)\n ? { 'accessibility-label': props.accessibilityLabel ?? title ?? '' }\n : {})}\n bindtap={press}\n >\n {form ? (\n <view className=\"g9-switch__text\">\n {title ? (\n <text className=\"g9-switch__title\" style={g9TextStart(control.direction)}>\n {title}\n </text>\n ) : null}\n {description ? (\n <text className=\"g9-switch__description\" style={g9TextStart(control.direction)}>\n {description}\n </text>\n ) : null}\n </view>\n ) : null}\n <view\n key={`shake-${shake}`}\n className={`g9-switch__track${shake > 0 ? ' g9-switch__track--shake' : ''}`}\n style={{ width: `${width}px`, height: `${G9Metrics.SwitchHeight}px`, backgroundColor: track }}\n >\n <view\n className=\"g9-switch__mark\"\n style={{ [rtl ? 'right' : 'left']: checked ? `${width - 15 - 6}px` : '12px' }}\n >\n {checked ? <text className=\"g9-switch__tick\">✓</text> : <view className=\"g9-switch__dot\" />}\n </view>\n <view\n className=\"g9-switch__thumb\"\n style={{\n [rtl ? 'right' : 'left']: '4px',\n width: `${thumb}px`,\n height: `${thumb}px`,\n backgroundColor: thumbColor,\n transform: `translateX(${x}px)`,\n }}\n />\n </view>\n </view>\n );\n});\n"],"names":["registries","WeakMap","globalScope","groupSet","scope","group","groups","Map","set","Set","SwitchGroupContext","createContext","G9SwitchGroup","props","control","useG9Control","states","setStates","useState","latest","useRef","minOneActive","minRef","value","n","on","id","current","next","active","total","notify","useEffect","warn","view","text","switchIds","G9Switch","forwardRef","ref","_props_defaultChecked","_props_accessibilityLabel","_ref","theme","useG9Theme","strings","useG9Strings","core","useContext","G9CoreContext","checked","setChecked","useControllableState","shake","setShake","latestChecked","setRef","groupName","memberRef","member","other","toggle","useImperativeHandle","press","useG9Press","rtl","width","G9Metrics","thumb","travel","x","track","formatColor","switchOnTrack","switchOffTrack","thumbColor","switchThumbOn","switchThumbOff","form","title","description","g9RowStyle","G9StringKey","g9TextStart"],"mappings":"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"}
1
+ {"version":3,"file":"toggle/switch.jsx","sources":["../../src/toggle/switch.tsx"],"sourcesContent":["import './toggle.css';\nimport {\n formatColor,\n G9Metrics,\n G9StringKey,\n switchOffTrack,\n switchOnTrack,\n switchThumbOff,\n switchThumbOn,\n} from '@g9tm/lynxcontrols-foundation';\nimport {\n createContext,\n forwardRef,\n type ReactNode,\n useContext,\n useEffect,\n useImperativeHandle,\n useRef,\n useState,\n} from '@lynx-js/react';\nimport { type G9ControlBaseProps, g9RowStyle, g9TextStart, useG9Control } from '../base/control';\nimport { useG9Press } from '../base/press';\nimport { useControllableState } from '../base/use-controllable-state';\nimport { G9CoreContext } from '../provider/contexts';\nimport { useG9Strings, useG9Theme } from '../provider/hooks';\n\n// ---- selection groups (MAUI `SelectionGroup`: radio-style, scoped to the provider) -------------------------------\n\ninterface GroupMember {\n turnOff(): void;\n}\n\nconst registries = new WeakMap<object, Map<string, Set<GroupMember>>>();\nconst globalScope = {};\n\nfunction groupSet(scope: object, group: string): Set<GroupMember> {\n let groups = registries.get(scope);\n if (!groups) {\n groups = new Map();\n registries.set(scope, groups);\n }\n let set = groups.get(group);\n if (!set) {\n set = new Set();\n groups.set(group, set);\n }\n return set;\n}\n\n// ---- G9SwitchGroup ---------------------------------------------------------------------------------------------\n\ninterface SwitchGroupContextValue {\n readonly minOneActive: boolean;\n activeCount(): number;\n report(id: number, on: boolean | null): void;\n}\n\nconst SwitchGroupContext = createContext<SwitchGroupContextValue | null>(null);\n\n/** Props of {@link G9SwitchGroup} (MAUI `G9SwitchGroup`). */\nexport interface G9SwitchGroupProps extends G9ControlBaseProps {\n /** A tap cannot turn off the last active switch of the group (it shakes). Default false. */\n readonly minOneActive?: boolean;\n /** Shows `active / total` under the switches (warning colour at ≤ 1 with `minOneActive`). Default false. */\n readonly showLiveStatus?: boolean;\n /** Told when the number of active switches changes (MAUI `ActiveSwitchCount`). */\n readonly onActiveCountChange?: (active: number, total: number) => void;\n readonly children?: ReactNode;\n}\n\n/**\n * A vertical group of switches (MAUI `G9SwitchGroup`): counts its switches (nearest group only, as MAUI's direct\n * children), optionally keeps one on and shows a live `active / total` status. It does not make switches exclusive:\n * use `selectionGroup` for radio behaviour.\n */\nexport function G9SwitchGroup(props: G9SwitchGroupProps): ReactNode {\n const control = useG9Control(props, 'g9-switch-group');\n const [states, setStates] = useState<ReadonlyMap<number, boolean>>(() => new Map());\n const latest = useRef(states);\n latest.current = states;\n const minOneActive = props.minOneActive === true;\n const minRef = useRef(minOneActive);\n minRef.current = minOneActive;\n // One context object for the group's life: switches key their effects on it.\n const value = useRef<SwitchGroupContextValue | null>(null);\n if (value.current === null) {\n value.current = {\n get minOneActive() {\n return minRef.current;\n },\n activeCount: () => {\n let n = 0;\n for (const on of latest.current.values()) if (on) n++;\n return n;\n },\n report: (id, on) =>\n setStates((current) => {\n if (on === null ? !current.has(id) : current.get(id) === on) return current;\n const next = new Map(current);\n if (on === null) next.delete(id);\n else next.set(id, on);\n latest.current = next;\n return next;\n }),\n };\n }\n let active = 0;\n for (const on of states.values()) if (on) active++;\n const total = states.size;\n const notify = useRef(props.onActiveCountChange);\n notify.current = props.onActiveCountChange;\n useEffect(() => {\n notify.current?.(active, total);\n }, [active, total]);\n const warn = minOneActive && active <= 1;\n return (\n <SwitchGroupContext.Provider value={value.current}>\n <view className={control.className} {...control.idProps}>\n {props.children}\n {props.showLiveStatus ? (\n <text\n className=\"g9-switch-group__status\"\n style={{ color: warn ? 'var(--g9-warning)' : 'var(--g9-text-tertiary)' }}\n >\n {`${active} / ${total}`}\n </text>\n ) : null}\n </view>\n </SwitchGroupContext.Provider>\n );\n}\n\n// ---- G9Switch ----------------------------------------------------------------------------------------------------\n\n/** Props of {@link G9Switch} (MAUI `G9Switch`). */\nexport interface G9SwitchProps extends G9ControlBaseProps {\n /** Controlled state (MAUI `IsOn`). */\n readonly checked?: boolean;\n readonly defaultChecked?: boolean;\n /**\n * Once per change made by the switch: a tap, `toggle()`, or being turned off by its selection group (MAUI\n * `Toggled`). Never for a value the parent pushed in.\n */\n readonly onCheckedChange?: (checked: boolean) => void;\n /** A tap cannot turn it off (it shakes); code still can. Default false. */\n readonly isRequired?: boolean;\n /** Radio group name: turning this on turns off the others with the same name under the same provider. */\n readonly selectionGroup?: string | null;\n /** Form row: title/description fill the start, switch at the end, padded. Default false. */\n readonly isInFormRow?: boolean;\n /** Bold 14 title (form row only); the accessibility name. */\n readonly title?: string | null;\n /** 12 px description under the title (form row only). */\n readonly description?: string | null;\n}\n\n/** Imperative handle of {@link G9Switch}. */\nexport interface G9SwitchHandle {\n /** Same as a tap. */\n toggle(): void;\n}\n\nlet switchIds = 0;\n\n/**\n * Switch (MAUI `G9Switch`): 56 × 32 track, 24 px thumb that stretches while travelling, 240 ms spring-like CSS\n * transition, tick/dot track mark; RTL moves the \"on\" side to the left. A blocked tap (required, or the last active\n * switch of a `minOneActive` group) shakes instead of toggling. Disabled: opacity 0.45.\n */\nexport const G9Switch = forwardRef<G9SwitchHandle, G9SwitchProps>(function G9Switch(props, ref): ReactNode {\n const control = useG9Control(props, 'g9-switch');\n const theme = useG9Theme();\n const strings = useG9Strings();\n const core = useContext(G9CoreContext);\n const group = useContext(SwitchGroupContext);\n const [checked, setChecked] = useControllableState<boolean>({\n value: props.checked,\n defaultValue: props.defaultChecked ?? false,\n onChange: props.onCheckedChange,\n name: 'G9Switch.checked',\n });\n const [shake, setShake] = useState(0);\n const id = useRef(0);\n if (id.current === 0) id.current = ++switchIds;\n const latestChecked = useRef(checked);\n latestChecked.current = checked;\n const setRef = useRef(setChecked);\n setRef.current = setChecked;\n\n // Report to the group.\n useEffect(() => {\n group?.report(id.current, checked);\n }, [group, checked]);\n useEffect(() => () => group?.report(id.current, null), [group]);\n\n // Selection group registration (while mounted and named).\n const groupName = props.selectionGroup && props.selectionGroup.trim() !== '' ? props.selectionGroup : null;\n const scope: object = core ?? globalScope;\n const memberRef = useRef<GroupMember | null>(null);\n useEffect(() => {\n if (!groupName) return;\n const member: GroupMember = { turnOff: () => setRef.current(false) };\n const set = groupSet(scope, groupName);\n set.add(member);\n memberRef.current = member;\n return () => {\n set.delete(member);\n memberRef.current = null;\n };\n }, [groupName, scope]);\n useEffect(() => {\n if (!checked || !groupName) return;\n for (const other of groupSet(scope, groupName)) if (other !== memberRef.current) other.turnOff();\n }, [checked, groupName, scope]);\n\n const toggle = () => {\n if (control.disabled) return;\n const on = latestChecked.current;\n if (on && (props.isRequired || (group?.minOneActive && group.activeCount() <= 1))) {\n setShake((n) => n + 1);\n return;\n }\n setChecked(!on);\n };\n useImperativeHandle(ref, () => ({ toggle }));\n const press = useG9Press(toggle, { blocked: control.disabled, source: 'G9Switch', guardMs: 0 });\n\n const rtl = control.direction === 'rtl';\n const width = G9Metrics.SwitchWidth;\n const thumb = G9Metrics.SwitchThumb;\n const travel = width - 4 - thumb - 4;\n const x = (checked ? travel : 0) * (rtl ? -1 : 1);\n const track = formatColor(checked ? switchOnTrack(theme) : switchOffTrack(theme));\n const thumbColor = formatColor(checked ? switchThumbOn(theme) : switchThumbOff(theme));\n const form = props.isInFormRow === true;\n const title = props.title && props.title.trim() !== '' ? props.title : null;\n const description = props.description && props.description.trim() !== '' ? props.description : null;\n return (\n <view\n className={`${control.className}${form ? ' g9-switch--row' : ''}`}\n {...control.idProps}\n style={g9RowStyle(control.direction)}\n accessibility-element={true}\n accessibility-traits=\"button\"\n {...(checked ? { 'accessibility-value': strings.get(G9StringKey.Selected) } : {})}\n {...((props.accessibilityLabel ?? title)\n ? { 'accessibility-label': props.accessibilityLabel ?? title ?? '' }\n : {})}\n bindtap={press}\n >\n {form ? (\n <view className=\"g9-switch__text\">\n {title ? (\n <text className=\"g9-switch__title\" style={g9TextStart(control.direction)}>\n {title}\n </text>\n ) : null}\n {description ? (\n <text className=\"g9-switch__description\" style={g9TextStart(control.direction)}>\n {description}\n </text>\n ) : null}\n </view>\n ) : null}\n <view\n key={`shake-${shake}`}\n className={`g9-switch__track${shake > 0 ? ' g9-switch__track--shake' : ''}`}\n style={{ width: `${width}px`, height: `${G9Metrics.SwitchHeight}px`, backgroundColor: track }}\n >\n {/* MAUI G9SwitchDrawable.DrawTrackMark: the mark is ALWAYS 15 dp from the track's start edge — on, the thumb has\n travelled to the end and the tick shows beside it; off, the thumb covers the dot. (Centring the tick at\n the end put it under the thumb: no tick was ever visible.) */}\n <view className=\"g9-switch__mark\" style={{ [rtl ? 'right' : 'left']: checked ? '9px' : '12px' }}>\n {checked ? <text className=\"g9-switch__tick\">✓</text> : <view className=\"g9-switch__dot\" />}\n </view>\n <view\n className=\"g9-switch__thumb\"\n style={{\n [rtl ? 'right' : 'left']: '4px',\n width: `${thumb}px`,\n height: `${thumb}px`,\n backgroundColor: thumbColor,\n transform: `translateX(${x}px)`,\n }}\n />\n </view>\n </view>\n );\n});\n"],"names":["registries","WeakMap","globalScope","groupSet","scope","group","groups","Map","set","Set","SwitchGroupContext","createContext","G9SwitchGroup","props","control","useG9Control","states","setStates","useState","latest","useRef","minOneActive","minRef","value","n","on","id","current","next","active","total","notify","useEffect","warn","view","text","switchIds","G9Switch","forwardRef","ref","_props_defaultChecked","_props_accessibilityLabel","_ref","theme","useG9Theme","strings","useG9Strings","core","useContext","G9CoreContext","checked","setChecked","useControllableState","shake","setShake","latestChecked","setRef","groupName","memberRef","member","other","toggle","useImperativeHandle","press","useG9Press","rtl","width","G9Metrics","thumb","travel","x","track","formatColor","switchOnTrack","switchOffTrack","thumbColor","switchThumbOn","switchThumbOff","form","title","description","g9RowStyle","G9StringKey","g9TextStart"],"mappings":";;;;;;;;AAgCA,MAAMA,aAAa,IAAIC;AACvB,MAAMC,cAAc,CAAC;AAErB,SAASC,SAASC,KAAa,EAAEC,KAAa;IAC5C,IAAIC,SAASN,WAAW,GAAG,CAACI;IAC5B,IAAI,CAACE,QAAQ;QACXA,SAAS,IAAIC;QACbP,WAAW,GAAG,CAACI,OAAOE;IACxB;IACA,IAAIE,MAAMF,OAAO,GAAG,CAACD;IACrB,IAAI,CAACG,KAAK;QACRA,MAAM,IAAIC;QACVH,OAAO,GAAG,CAACD,OAAOG;IACpB;IACA,OAAOA;AACT;AAUA,MAAME,qBAAqBC,cAA8C;AAkBlE,SAASC,cAAcC,KAAyB;IACrD,MAAMC,UAAUC,aAAaF,OAAO;IACpC,MAAM,CAACG,QAAQC,UAAU,GAAGC,SAAuC,IAAM,IAAIX;IAC7E,MAAMY,SAASC,OAAOJ;IACtBG,OAAO,OAAO,GAAGH;IACjB,MAAMK,eAAeR,AAAuB,SAAvBA,MAAM,YAAY;IACvC,MAAMS,SAASF,OAAOC;IACtBC,OAAO,OAAO,GAAGD;IAEjB,MAAME,QAAQH,OAAuC;IACrD,IAAIG,AAAkB,SAAlBA,MAAM,OAAO,EACfA,MAAM,OAAO,GAAG;QACd,IAAI;YACF,OAAOD,OAAO,OAAO;QACvB;QACA,aAAa;YACX,IAAIE,IAAI;YACR,KAAK,MAAMC,MAAMN,OAAO,OAAO,CAAC,MAAM,GAAI,IAAIM,IAAID;YAClD,OAAOA;QACT;QACA,QAAQ,CAACE,IAAID,KACXR,UAAU,CAACU;gBACT,IAAIF,AAAO,SAAPA,KAAc,CAACE,QAAQ,GAAG,CAACD,MAAMC,QAAQ,GAAG,CAACD,QAAQD,IAAI,OAAOE;gBACpE,MAAMC,OAAO,IAAIrB,IAAIoB;gBACrB,IAAIF,AAAO,SAAPA,IAAaG,KAAK,MAAM,CAACF;qBACxBE,KAAK,GAAG,CAACF,IAAID;gBAClBN,OAAO,OAAO,GAAGS;gBACjB,OAAOA;YACT;IACJ;IAEF,IAAIC,SAAS;IACb,KAAK,MAAMJ,MAAMT,OAAO,MAAM,GAAI,IAAIS,IAAII;IAC1C,MAAMC,QAAQd,OAAO,IAAI;IACzB,MAAMe,SAASX,OAAOP,MAAM,mBAAmB;IAC/CkB,OAAO,OAAO,GAAGlB,MAAM,mBAAmB;IAC1CmB,UAAU;YACRD;gBAAAA,CAAAA,kBAAAA,OAAO,OAAO,AAAD,KAAbA,gBAAAA,IAAAA,CAAAA,QAAiBF,QAAQC;IAC3B,GAAG;QAACD;QAAQC;KAAM;IAClB,MAAMG,OAAOZ,gBAAgBQ,UAAU;IACvC,QACGnB,mBAAmB,SAAS,OAAOa,MAAM,OAAO,EAAE;MACjD,CAACW,KAAK,WAAWpB,QAAQ,SAAS,GAAG,GAAGA,QAAQ,OAAO,EAAE;QACvD,CAACD,MAAM,QAAQ,CAAC;QAChB,CAACA,MAAM,cAAc,IAClBsB,KACC,UAAU,0BACV,OAAO;QAAE,OAAOF,OAAO,sBAAsB;IAA0B,GACxE;YACC,CAAC,GAAGJ,OAAO,GAAG,EAAEC,OAAO,CAAC;UAC1B,EAAEK,QACA,KAAK;MACX,EAAED,KAAK;IACT,EAAExB,mBAAmB;AAEzB;AAgCA,IAAI0B,YAAY;AAOT,MAAMC,kBAAWC,WAA0C,SAAkBzB,KAAK,EAAE0B,GAAG;QAQ5EC,uBAoENC,2BACuBC,MAAAA;IA5EjC,MAAM5B,UAAUC,aAAaF,OAAO;IACpC,MAAM8B,QAAQC;IACd,MAAMC,UAAUC;IAChB,MAAMC,OAAOC,WAAWC;IACxB,MAAM5C,QAAQ2C,WAAWtC;IACzB,MAAM,CAACwC,SAASC,WAAW,GAAGC,qBAA8B;QAC1D,OAAOvC,MAAM,OAAO;QACpB,cAAc,QAAA2B,CAAAA,wBAAAA,MAAM,cAAc,AAAD,IAAnBA,wBAAwB;QACtC,UAAU3B,MAAM,eAAe;QAC/B,MAAM;IACR;IACA,MAAM,CAACwC,OAAOC,SAAS,GAAGpC,SAAS;IACnC,MAAMQ,KAAKN,OAAO;IAClB,IAAIM,AAAe,MAAfA,GAAG,OAAO,EAAQA,GAAG,OAAO,GAAG,EAAEU;IACrC,MAAMmB,gBAAgBnC,OAAO8B;IAC7BK,cAAc,OAAO,GAAGL;IACxB,MAAMM,SAASpC,OAAO+B;IACtBK,OAAO,OAAO,GAAGL;IAGjBnB,UAAU;QACR3B,QAAAA,SAAAA,MAAO,MAAM,CAACqB,GAAG,OAAO,EAAEwB;IAC5B,GAAG;QAAC7C;QAAO6C;KAAQ;IACnBlB,UAAU,IAAM,IAAM3B,QAAAA,QAAAA,KAAAA,IAAAA,MAAO,MAAM,CAACqB,GAAG,OAAO,EAAE,OAAO;QAACrB;KAAM;IAG9D,MAAMoD,YAAY5C,MAAM,cAAc,IAAIA,AAAgC,OAAhCA,MAAM,cAAc,CAAC,IAAI,KAAYA,MAAM,cAAc,GAAG;IACtG,MAAMT,QAAgB2C,QAAAA,OAAAA,OAAQ7C;IAC9B,MAAMwD,YAAYtC,OAA2B;IAC7CY,UAAU;QACR,IAAI,CAACyB,WAAW;QAChB,MAAME,SAAsB;YAAE,SAAS,IAAMH,OAAO,OAAO,CAAC;QAAO;QACnE,MAAMhD,MAAML,SAASC,OAAOqD;QAC5BjD,IAAI,GAAG,CAACmD;QACRD,UAAU,OAAO,GAAGC;QACpB,OAAO;YACLnD,IAAI,MAAM,CAACmD;YACXD,UAAU,OAAO,GAAG;QACtB;IACF,GAAG;QAACD;QAAWrD;KAAM;IACrB4B,UAAU;QACR,IAAI,CAACkB,WAAW,CAACO,WAAW;QAC5B,KAAK,MAAMG,SAASzD,SAASC,OAAOqD,WAAY,IAAIG,UAAUF,UAAU,OAAO,EAAEE,MAAM,OAAO;IAChG,GAAG;QAACV;QAASO;QAAWrD;KAAM;IAE9B,MAAMyD,SAAS;QACb,IAAI/C,QAAQ,QAAQ,EAAE;QACtB,MAAMW,KAAK8B,cAAc,OAAO;QAChC,IAAI9B,MAAOZ,CAAAA,MAAM,UAAU,IAAKR,AAAAA,CAAAA,QAAAA,QAAAA,KAAAA,IAAAA,MAAO,YAAY,AAAD,KAAKA,MAAM,WAAW,MAAM,IAAK,YACjFiD,SAAS,CAAC9B,IAAMA,IAAI;QAGtB2B,WAAW,CAAC1B;IACd;IACAqC,oBAAoBvB,KAAK,IAAO;YAAEsB;QAAO;IACzC,MAAME,QAAQC,WAAWH,QAAQ;QAAE,SAAS/C,QAAQ,QAAQ;QAAE,QAAQ;QAAY,SAAS;IAAE;IAE7F,MAAMmD,MAAMnD,AAAsB,UAAtBA,QAAQ,SAAS;IAC7B,MAAMoD,QAAQC,UAAU,WAAW;IACnC,MAAMC,QAAQD,UAAU,WAAW;IACnC,MAAME,SAASH,QAAQ,IAAIE,QAAQ;IACnC,MAAME,IAAKpB,AAAAA,CAAAA,UAAUmB,SAAS,KAAMJ,CAAAA,MAAM,KAAK;IAC/C,MAAMM,QAAQC,YAAYtB,UAAUuB,cAAc9B,SAAS+B,eAAe/B;IAC1E,MAAMgC,aAAaH,YAAYtB,UAAU0B,cAAcjC,SAASkC,eAAelC;IAC/E,MAAMmC,OAAOjE,AAAsB,SAAtBA,MAAM,WAAW;IAC9B,MAAMkE,QAAQlE,MAAM,KAAK,IAAIA,AAAuB,OAAvBA,MAAM,KAAK,CAAC,IAAI,KAAYA,MAAM,KAAK,GAAG;IACvE,MAAMmE,cAAcnE,MAAM,WAAW,IAAIA,AAA6B,OAA7BA,MAAM,WAAW,CAAC,IAAI,KAAYA,MAAM,WAAW,GAAG;IAC/F,QACGqB,KACC,WAAW,GAAGpB,QAAQ,SAAS,GAAGgE,OAAO,oBAAoB,IAAI,GAChE,GAAGhE,QAAQ,OAAO,EACnB,OAAOmE,WAAWnE,QAAQ,SAAS,GACnC,uBAAuB,MACvB,qBAAqB,UACpB,GAAIoC,UAAU;QAAE,uBAAuBL,QAAQ,GAAG,CAACqC,YAAY,QAAQ;IAAE,IAAI,CAAC,CAAC,GAC/E,GAAI,AAAC,SAAAzC,CAAAA,4BAAAA,MAAM,kBAAkB,AAAD,IAAvBA,4BAA4BsC,KAAI,IAClC;QAAE,uBAAuB,QAAArC,CAAAA,OAAAA,QAAAA,CAAAA,6BAAAA,MAAM,kBAAkB,AAAD,IAAvBA,6BAA4BqC,KAAI,IAAhCrC,OAAqC;IAAG,IACjE,CAAC,CAAC,EACN,SAASqB,OACV;MACC,CAACe,QACE5C,KAAK,UAAU,kBAAkB;UAChC,CAAC6C,SACE5C,KAAK,UAAU,mBAAmB,OAAOgD,YAAYrE,QAAQ,SAAS,GAAG;cACxE,CAACiE,MAAM;YACT,EAAE5C,QACA,KAAK;UACT,CAAC6C,eACE7C,KAAK,UAAU,yBAAyB,OAAOgD,YAAYrE,QAAQ,SAAS,GAAG;cAC9E,CAACkE,YAAY;YACf,EAAE7C,QACA,KAAK;QACX,EAAED,QACA,KAAK;MACT,CAACA,KACC,KAAK,CAAC,MAAM,EAAEmB,OAAO,EACrB,WAAW,CAAC,gBAAgB,EAAEA,QAAQ,IAAI,6BAA6B,IAAI,EAC3E,OAAO;QAAE,OAAO,GAAGa,MAAM,EAAE,CAAC;QAAE,QAAQ,GAAGC,UAAU,YAAY,CAAC,EAAE,CAAC;QAAE,iBAAiBI;IAAM,GAC7F;QACC,EAEkE;QAClE,CAACrC,KAAK,UAAU,kBAAkB,OAAO;QAAE,CAAC+B,MAAM,UAAU,OAAO,EAAEf,UAAU,QAAQ;IAAO,GAAG;UAC/F,CAACA,WAAWf,KAAK,UAAU,kBAAkB,CAAC,EAAEA,SAASD,KAAK,UAAU,mBAAoB;QAC9F,EAAEA,KAAK;QACP,CAACA,KACC,UAAU,mBACV,OAAO;QACL,CAAC+B,MAAM,UAAU,OAAO,EAAE;QAC1B,OAAO,GAAGG,MAAM,EAAE,CAAC;QACnB,QAAQ,GAAGA,MAAM,EAAE,CAAC;QACpB,iBAAiBO;QACjB,WAAW,CAAC,WAAW,EAAEL,EAAE,GAAG,CAAC;IACjC,IACA;MACJ,EAAEpC,KAAK;IACT,EAAEA;AAEN"}
@@ -113,7 +113,10 @@
113
113
 
114
114
  .g9-switch__tick {
115
115
  color: #ffffffbf;
116
- font-size: 12px;
116
+ margin-top: -2px;
117
+ font-size: 15px;
118
+ font-weight: bold;
119
+ line-height: 15px;
117
120
  }
118
121
 
119
122
  .g9-switch__dot {
@@ -140,7 +143,7 @@
140
143
 
141
144
  .g9-chip-group--wrap {
142
145
  flex-flow: wrap;
143
- justify-content: center;
146
+ justify-content: flex-start;
144
147
  display: flex;
145
148
  }
146
149
 
@@ -1 +1 @@
1
- {"version":3,"sources":["webpack://./src/toggle/toggle.css"],"names":[],"mappings":"AACA;EAAE,mBAAmB;EACnB,sBAAsB;EACtB,uBAAuB;EACvB,aAAa;AACf;;AAGA;EAAE,mBAAmB;EACnB,eAAe;AACjB;;AAGA;EAAE,uBAAuB;EACvB,mBAAmB;EACnB,aAAa;AACf;;AAKA;EAFE,YAAY;AACd;;AAKA;EAFE,WAAW;EACX,YAAY;AACd;;AAOA;EAJE,OAAO;EACP,kBAAkB;EAClB,eAAe;AACjB;;AAOA;EAJE,mBAAmB;EACnB,uBAAuB;EACvB,mBAAmB;EACnB,aAAa;AACf;;AAOA;EAJE,8BAA8B;EAC9B,mBAAmB;EACnB,gBAAgB;EAChB,kBAAkB;AACpB;;AAOA;EAJE,sBAAsB;EACtB,OAAO;EACP,YAAY;EACZ,aAAa;AACf;;AAOA;EAJE,6BAA6B;EAC7B,eAAe;EACf,iBAAiB;AACnB;;AAOA;EAJE,8BAA8B;EAC9B,eAAe;AACjB;;AAOA;EAJE,mBAAmB;EACnB,0CAA0C;EAC1C,kBAAkB;AACpB;;AAOA;EAJE,2CAA2C;AAC7C;;AAOA;EAJE;IACE,wBAAwB;EAC1B;;EAEA;IACE,2BAA2B;EAC7B;;EAEA;IACE,0BAA0B;EAC5B;;EAEA;IACE,2BAA2B;EAC7B;;EAEA;IACE,0BAA0B;EAC5B;;EAEA;IACE,wBAAwB;EAC1B;AACF;;AAEA;EACE,mBAAmB;EACnB,0FAA0F;EAC1F,kBAAkB;EAClB,QAAQ;AACV;;AAIA;EADE,kBAAkB;EAClB,QAAQ;AACV;;AAIA;EADE,gBAAgB;EAChB,eAAe;AACjB;;AAIA;EADE,2BAA2B;EAC3B,kBAAkB;EAClB,UAAU;EACV,WAAW;EACX,eAAe;AACjB;;AAIA;EADE,YAAY;AACd;;AAIA;EADE,sBAAsB;EACtB,aAAa;AACf;;AAIA;EADE,iBAAiB;EACjB,eAAe;AACjB;;AAIA;EADE,eAAe;EACf,uBAAuB;EACvB,aAAa;AACf;;AAKA;EAFE,mBAAmB;EACnB,aAAa;AACf;;AAKA;EAFE,mBAAmB;EACnB,mBAAmB;EACnB,mBAAmB;EACnB,mBAAmB;EACnB,eAAe;EACf,eAAe;EACf,4EAA4E;EAC5E,aAAa;AACf;;AAOA;EAJE,YAAY;AACd;;AAOA;EAJE,mBAAmB;EACnB,eAAe;EACf,iBAAiB;AACnB;;AAOA;EAJE,UAAU;EACV,QAAQ;EACR,wFAAwF;EACxF,gBAAgB;EAChB,oBAAoB;AACtB;;AAUA;EAPE,UAAU;EACV,WAAW;EACX,mBAAmB;AACrB","sourcesContent":["/* Toggles (MAUI G9CheckBox, G9Switch, G9SwitchGroup, G9ChipGroup). */\n.g9-checkbox {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n align-self: flex-start;\n}\n\n.g9-checkbox--labelled {\n align-self: stretch;\n column-gap: 2px;\n}\n\n.g9-checkbox__slot {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* MAUI G9CheckBox: the 20 px box is centred in a 48 × 48 slot (both axes). The slot used to put it at the start edge\n and 7 px low (row direction + padding), 28 px from its label on Android. */\n.g9-checkbox__slot--reserve {\n height: 48px;\n}\n\n.g9-checkbox__box {\n width: 20px;\n height: 20px;\n}\n\n/* One line centres on the slot (MAUI: label centred in the 48 px row); a wrapping label grows the row and the box\n stays level with its first line. */\n.g9-checkbox__text {\n flex: 1;\n align-self: center;\n font-size: 14px;\n}\n\n.g9-switch {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n}\n\n.g9-switch--row {\n justify-content: space-between;\n column-gap: 12px;\n padding: 12px 16px;\n align-self: stretch;\n}\n\n.g9-switch__text {\n display: flex;\n flex-direction: column;\n flex: 1;\n row-gap: 2px;\n}\n\n.g9-switch__title {\n font-size: 14px;\n font-weight: bold;\n color: var(--g9-text-primary);\n}\n\n.g9-switch__description {\n font-size: 12px;\n color: var(--g9-text-tertiary);\n}\n\n.g9-switch__track {\n position: relative;\n border-radius: 16px;\n transition: background-color 240ms ease-out;\n}\n\n.g9-switch__track--shake {\n animation: g9-switch-shake 310ms ease-in-out;\n}\n\n@keyframes g9-switch-shake {\n 0% {\n transform: translateX(0px);\n }\n 19% {\n transform: translateX(-4px);\n }\n 39% {\n transform: translateX(4px);\n }\n 58% {\n transform: translateX(-3px);\n }\n 77% {\n transform: translateX(3px);\n }\n 100% {\n transform: translateX(0px);\n }\n}\n\n.g9-switch__thumb {\n position: absolute;\n top: 4px;\n border-radius: 12px;\n transition:\n transform 240ms cubic-bezier(0.34, 1.56, 0.64, 1),\n background-color 240ms ease-out;\n}\n\n.g9-switch__mark {\n position: absolute;\n top: 9px;\n}\n\n.g9-switch__tick {\n font-size: 12px;\n color: rgba(255, 255, 255, 0.75);\n}\n\n.g9-switch__dot {\n width: 6px;\n height: 6px;\n margin-top: 4px;\n border-radius: 3px;\n background-color: rgba(0, 0, 0, 0.22);\n}\n\n.g9-disabled {\n opacity: 0.45;\n}\n\n.g9-switch-group {\n display: flex;\n flex-direction: column;\n}\n\n.g9-switch-group__status {\n font-size: 11px;\n margin: 6px 2px 0px 2px;\n}\n\n.g9-chip-group--wrap {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: center;\n}\n\n.g9-chip-group__line {\n display: flex;\n flex-direction: row;\n}\n\n.g9-chip {\n display: flex;\n flex-direction: row;\n align-items: center;\n column-gap: 6px;\n padding: 0px 14px;\n border-style: solid;\n border-width: 1.5px;\n transition:\n background-color 140ms ease-in-out,\n border-color 140ms ease-in-out;\n}\n\n.g9-chip--disabled {\n opacity: 0.45;\n}\n\n.g9-chip__text {\n font-size: 13px;\n font-weight: bold;\n white-space: nowrap;\n}\n\n.g9-chip__check {\n width: 0px;\n opacity: 0;\n transform: scale(0.5);\n overflow: hidden;\n transition:\n width 120ms ease-in-out,\n opacity 120ms ease-in-out,\n transform 120ms ease-in-out;\n}\n\n.g9-chip__check--on {\n width: 16px;\n opacity: 1;\n transform: scale(1);\n}\n"],"sourceRoot":""}
1
+ {"version":3,"sources":["webpack://./src/toggle/toggle.css"],"names":[],"mappings":"AACA;EAAE,mBAAmB;EACnB,sBAAsB;EACtB,uBAAuB;EACvB,aAAa;AACf;;AAGA;EAAE,mBAAmB;EACnB,eAAe;AACjB;;AAGA;EAAE,uBAAuB;EACvB,mBAAmB;EACnB,aAAa;AACf;;AAKA;EAFE,YAAY;AACd;;AAKA;EAFE,WAAW;EACX,YAAY;AACd;;AAOA;EAJE,OAAO;EACP,kBAAkB;EAClB,eAAe;AACjB;;AAOA;EAJE,mBAAmB;EACnB,uBAAuB;EACvB,mBAAmB;EACnB,aAAa;AACf;;AAOA;EAJE,8BAA8B;EAC9B,mBAAmB;EACnB,gBAAgB;EAChB,kBAAkB;AACpB;;AAOA;EAJE,sBAAsB;EACtB,OAAO;EACP,YAAY;EACZ,aAAa;AACf;;AAOA;EAJE,6BAA6B;EAC7B,eAAe;EACf,iBAAiB;AACnB;;AAOA;EAJE,8BAA8B;EAC9B,eAAe;AACjB;;AAOA;EAJE,mBAAmB;EACnB,0CAA0C;EAC1C,kBAAkB;AACpB;;AAOA;EAJE,2CAA2C;AAC7C;;AAOA;EAJE;IACE,wBAAwB;EAC1B;;EAEA;IACE,2BAA2B;EAC7B;;EAEA;IACE,0BAA0B;EAC5B;;EAEA;IACE,2BAA2B;EAC7B;;EAEA;IACE,0BAA0B;EAC5B;;EAEA;IACE,wBAAwB;EAC1B;AACF;;AAEA;EACE,mBAAmB;EACnB,0FAA0F;EAC1F,kBAAkB;EAClB,QAAQ;AACV;;AAIA;EADE,kBAAkB;EAClB,QAAQ;AACV;;AAKA;EAFE,gBAAgB;EAChB,gBAAgB;EAChB,eAAe;EACf,iBAAiB;EACjB,iBAAiB;AACnB;;AAKA;EAFE,2BAA2B;EAC3B,kBAAkB;EAClB,UAAU;EACV,WAAW;EACX,eAAe;AACjB;;AAKA;EAFE,YAAY;AACd;;AAKA;EAFE,sBAAsB;EACtB,aAAa;AACf;;AAKA;EAFE,iBAAiB;EACjB,eAAe;AACjB;;AAOA;EAJE,eAAe;EACf,2BAA2B;EAC3B,aAAa;AACf;;AAQA;EALE,mBAAmB;EACnB,aAAa;AACf;;AAQA;EALE,mBAAmB;EACnB,mBAAmB;EACnB,mBAAmB;EACnB,mBAAmB;EACnB,eAAe;EACf,eAAe;EACf,4EAA4E;EAC5E,aAAa;AACf;;AAUA;EAPE,YAAY;AACd;;AAUA;EAPE,mBAAmB;EACnB,eAAe;EACf,iBAAiB;AACnB;;AAUA;EAPE,UAAU;EACV,QAAQ;EACR,wFAAwF;EACxF,gBAAgB;EAChB,oBAAoB;AACtB;;AAaA;EAVE,UAAU;EACV,WAAW;EACX,mBAAmB;AACrB","sourcesContent":["/* Toggles (MAUI G9CheckBox, G9Switch, G9SwitchGroup, G9ChipGroup). */\n.g9-checkbox {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n align-self: flex-start;\n}\n\n.g9-checkbox--labelled {\n align-self: stretch;\n column-gap: 2px;\n}\n\n.g9-checkbox__slot {\n display: flex;\n align-items: center;\n justify-content: center;\n}\n\n/* MAUI G9CheckBox: the 20 px box is centred in a 48 × 48 slot (both axes). The slot used to put it at the start edge\n and 7 px low (row direction + padding), 28 px from its label on Android. */\n.g9-checkbox__slot--reserve {\n height: 48px;\n}\n\n.g9-checkbox__box {\n width: 20px;\n height: 20px;\n}\n\n/* One line centres on the slot (MAUI: label centred in the 48 px row); a wrapping label grows the row and the box\n stays level with its first line. */\n.g9-checkbox__text {\n flex: 1;\n align-self: center;\n font-size: 14px;\n}\n\n.g9-switch {\n display: flex;\n flex-direction: row;\n align-items: center;\n justify-content: center;\n}\n\n.g9-switch--row {\n justify-content: space-between;\n column-gap: 12px;\n padding: 12px 16px;\n align-self: stretch;\n}\n\n.g9-switch__text {\n display: flex;\n flex-direction: column;\n flex: 1;\n row-gap: 2px;\n}\n\n.g9-switch__title {\n font-size: 14px;\n font-weight: bold;\n color: var(--g9-text-primary);\n}\n\n.g9-switch__description {\n font-size: 12px;\n color: var(--g9-text-tertiary);\n}\n\n.g9-switch__track {\n position: relative;\n border-radius: 16px;\n transition: background-color 240ms ease-out;\n}\n\n.g9-switch__track--shake {\n animation: g9-switch-shake 310ms ease-in-out;\n}\n\n@keyframes g9-switch-shake {\n 0% {\n transform: translateX(0px);\n }\n 19% {\n transform: translateX(-4px);\n }\n 39% {\n transform: translateX(4px);\n }\n 58% {\n transform: translateX(-3px);\n }\n 77% {\n transform: translateX(3px);\n }\n 100% {\n transform: translateX(0px);\n }\n}\n\n.g9-switch__thumb {\n position: absolute;\n top: 4px;\n border-radius: 12px;\n transition:\n transform 240ms cubic-bezier(0.34, 1.56, 0.64, 1),\n background-color 240ms ease-out;\n}\n\n.g9-switch__mark {\n position: absolute;\n top: 9px;\n}\n\n/* MAUI draws the tick with 2.5 dp round strokes, 11 × 9 dp: a bold 15 dp glyph is that weight and size. */\n.g9-switch__tick {\n font-size: 15px;\n font-weight: bold;\n line-height: 15px;\n margin-top: -2px;\n color: rgba(255, 255, 255, 0.75);\n}\n\n.g9-switch__dot {\n width: 6px;\n height: 6px;\n margin-top: 4px;\n border-radius: 3px;\n background-color: rgba(0, 0, 0, 0.22);\n}\n\n.g9-disabled {\n opacity: 0.45;\n}\n\n.g9-switch-group {\n display: flex;\n flex-direction: column;\n}\n\n.g9-switch-group__status {\n font-size: 11px;\n margin: 6px 2px 0px 2px;\n}\n\n/* MAUI G9ChipGroup: a FlexLayout of Wrap and JustifyContent Start — the chips run from the reading start (the row is\n reversed in RTL, so flex-start is the right edge there), never centred. */\n.g9-chip-group--wrap {\n display: flex;\n flex-direction: row;\n flex-wrap: wrap;\n justify-content: flex-start;\n}\n\n.g9-chip-group__line {\n display: flex;\n flex-direction: row;\n}\n\n.g9-chip {\n display: flex;\n flex-direction: row;\n align-items: center;\n column-gap: 6px;\n padding: 0px 14px;\n border-style: solid;\n border-width: 1.5px;\n transition:\n background-color 140ms ease-in-out,\n border-color 140ms ease-in-out;\n}\n\n.g9-chip--disabled {\n opacity: 0.45;\n}\n\n.g9-chip__text {\n font-size: 13px;\n font-weight: bold;\n white-space: nowrap;\n}\n\n.g9-chip__check {\n width: 0px;\n opacity: 0;\n transform: scale(0.5);\n overflow: hidden;\n transition:\n width 120ms ease-in-out,\n opacity 120ms ease-in-out,\n transform 120ms ease-in-out;\n}\n\n.g9-chip__check--on {\n width: 16px;\n opacity: 1;\n transform: scale(1);\n}\n"],"sourceRoot":""}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@g9tm/lynxcontrols",
3
- "version": "1.4.3",
3
+ "version": "1.4.5",
4
4
  "description": "ReactLynx controls and overlay infrastructure: provider/host, sheets, popups, toasts, fields, buttons, pickers, tab view, tab bar, edge panel, swipe rows.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -137,7 +137,7 @@
137
137
  "build": "rslib build"
138
138
  },
139
139
  "dependencies": {
140
- "@g9tm/lynxcontrols-foundation": "1.4.3",
140
+ "@g9tm/lynxcontrols-foundation": "1.4.5",
141
141
  "@lynx-js/lynx-ui-common": "3.139.0",
142
142
  "@lynx-js/lynx-ui-deferred-component": "3.139.0",
143
143
  "@lynx-js/lynx-ui-draggable": "3.139.0",