@7pmlabs/design-system 1.0.9 → 1.0.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (126) hide show
  1. package/dist/design-system.css +1 -1
  2. package/dist/design-system.js +24 -16
  3. package/dist/design-system177.js +29 -326
  4. package/dist/design-system177.js.map +1 -1
  5. package/dist/design-system179.js +1 -1
  6. package/dist/design-system179.js.map +1 -1
  7. package/dist/design-system180.js +73 -85
  8. package/dist/design-system180.js.map +1 -1
  9. package/dist/design-system182.js +1 -1
  10. package/dist/design-system182.js.map +1 -1
  11. package/dist/design-system183.js +32 -105
  12. package/dist/design-system183.js.map +1 -1
  13. package/dist/design-system185.js +4 -5
  14. package/dist/design-system185.js.map +1 -1
  15. package/dist/design-system186.js +26 -104
  16. package/dist/design-system186.js.map +1 -1
  17. package/dist/design-system188.js +4 -5
  18. package/dist/design-system188.js.map +1 -1
  19. package/dist/design-system189.js +23 -727
  20. package/dist/design-system189.js.map +1 -1
  21. package/dist/design-system191.js +1 -1
  22. package/dist/design-system191.js.map +1 -1
  23. package/dist/design-system192.js +31 -11
  24. package/dist/design-system192.js.map +1 -1
  25. package/dist/design-system194.js +8 -0
  26. package/dist/design-system194.js.map +1 -0
  27. package/dist/design-system195.js +332 -5
  28. package/dist/design-system195.js.map +1 -1
  29. package/dist/design-system197.js +5 -46
  30. package/dist/design-system197.js.map +1 -1
  31. package/dist/design-system198.js +100 -4
  32. package/dist/design-system198.js.map +1 -1
  33. package/dist/design-system200.js +8 -0
  34. package/dist/design-system200.js.map +1 -0
  35. package/dist/design-system201.js +19 -5
  36. package/dist/design-system201.js.map +1 -1
  37. package/dist/design-system202.js +4 -119
  38. package/dist/design-system202.js.map +1 -1
  39. package/dist/design-system203.js +6 -0
  40. package/dist/design-system203.js.map +1 -0
  41. package/dist/design-system204.js +419 -5
  42. package/dist/design-system204.js.map +1 -1
  43. package/dist/design-system206.js +8 -0
  44. package/dist/design-system206.js.map +1 -0
  45. package/dist/design-system207.js +108 -5
  46. package/dist/design-system207.js.map +1 -1
  47. package/dist/design-system209.js +6 -4
  48. package/dist/design-system209.js.map +1 -1
  49. package/dist/design-system210.js +90 -154
  50. package/dist/design-system210.js.map +1 -1
  51. package/dist/design-system212.js +5 -4
  52. package/dist/design-system212.js.map +1 -1
  53. package/dist/design-system213.js +737 -7
  54. package/dist/design-system213.js.map +1 -1
  55. package/dist/design-system215.js +8 -0
  56. package/dist/design-system215.js.map +1 -0
  57. package/dist/design-system216.js +11 -5
  58. package/dist/design-system216.js.map +1 -1
  59. package/dist/design-system217.js +451 -506
  60. package/dist/design-system217.js.map +1 -1
  61. package/dist/design-system219.js +4 -5
  62. package/dist/design-system219.js.map +1 -1
  63. package/dist/design-system220.js +3 -7
  64. package/dist/design-system220.js.map +1 -1
  65. package/dist/design-system221.js +41 -369
  66. package/dist/design-system221.js.map +1 -1
  67. package/dist/design-system222.js +7 -0
  68. package/dist/design-system222.js.map +1 -0
  69. package/dist/design-system223.js +283 -6
  70. package/dist/design-system223.js.map +1 -1
  71. package/dist/design-system225.js +8 -0
  72. package/dist/design-system225.js.map +1 -0
  73. package/dist/design-system226.js +122 -0
  74. package/dist/design-system226.js.map +1 -0
  75. package/dist/design-system228.js +8 -0
  76. package/dist/design-system228.js.map +1 -0
  77. package/dist/{design-system205.js → design-system229.js} +1 -1
  78. package/dist/{design-system205.js.map → design-system229.js.map} +1 -1
  79. package/dist/design-system231.js +8 -0
  80. package/dist/design-system231.js.map +1 -0
  81. package/dist/{design-system208.js → design-system232.js} +1 -1
  82. package/dist/{design-system208.js.map → design-system232.js.map} +1 -1
  83. package/dist/design-system233.js +7 -0
  84. package/dist/design-system233.js.map +1 -0
  85. package/dist/design-system234.js +173 -0
  86. package/dist/design-system234.js.map +1 -0
  87. package/dist/design-system236.js +8 -0
  88. package/dist/design-system236.js.map +1 -0
  89. package/dist/design-system237.js +10 -0
  90. package/dist/design-system237.js.map +1 -0
  91. package/dist/{design-system214.js → design-system238.js} +2 -2
  92. package/dist/{design-system214.js.map → design-system238.js.map} +1 -1
  93. package/dist/design-system240.js +8 -0
  94. package/dist/design-system240.js.map +1 -0
  95. package/dist/design-system241.js +583 -0
  96. package/dist/design-system241.js.map +1 -0
  97. package/dist/design-system243.js +9 -0
  98. package/dist/design-system243.js.map +1 -0
  99. package/dist/design-system244.js +10 -0
  100. package/dist/design-system244.js.map +1 -0
  101. package/dist/design-system245.js +377 -0
  102. package/dist/design-system245.js.map +1 -0
  103. package/dist/design-system247.js +9 -0
  104. package/dist/design-system247.js.map +1 -0
  105. package/dist/types/components/BSkeleton/BSkeleton.spec.d.ts +1 -0
  106. package/dist/types/components/BSkeleton/BSkeleton.vue.d.ts +46 -0
  107. package/dist/types/components/BSkeleton/BSkeletonAvatar.vue.d.ts +12 -0
  108. package/dist/types/components/BSkeleton/BSkeletonButton.vue.d.ts +14 -0
  109. package/dist/types/components/BSkeleton/BSkeletonImage.vue.d.ts +7 -0
  110. package/dist/types/components/BSkeleton/BSkeletonInput.vue.d.ts +12 -0
  111. package/dist/types/components/BSkeleton/BSkeletonNode.vue.d.ts +19 -0
  112. package/dist/types/components/BSkeleton/index.d.ts +7 -0
  113. package/dist/types/components/BSkeleton/types.d.ts +20 -0
  114. package/dist/types/components/BSplitter/BSplitter.spec.d.ts +1 -0
  115. package/dist/types/components/BSplitter/BSplitter.vue.d.ts +45 -0
  116. package/dist/types/components/BSplitter/BSplitterPanel.vue.d.ts +40 -0
  117. package/dist/types/components/BSplitter/index.d.ts +3 -0
  118. package/dist/types/components/BSplitter/types.d.ts +42 -0
  119. package/dist/types/components/index.d.ts +2 -0
  120. package/package.json +1 -1
  121. package/dist/design-system193.js +0 -528
  122. package/dist/design-system193.js.map +0 -1
  123. package/dist/design-system196.js +0 -6
  124. package/dist/design-system196.js.map +0 -1
  125. package/dist/design-system199.js +0 -286
  126. package/dist/design-system199.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design-system206.js","names":[],"sources":["../src/components/BSplitter/BSplitter.vue"],"sourcesContent":["<script lang=\"ts\" setup>\n/**\n * BSplitter\n * ---------\n * A flex container that lets the user resize the size of its panels by\n * dragging the bars between them.\n *\n * Mirrors the AntD `<Splitter>` API. Children must be `<BSplitterPanel>`\n * components.\n */\nimport type { CSSProperties, PropType, VNode } from 'vue';\nimport { Fragment, camelize, computed, defineComponent, h, onBeforeUnmount, onMounted, provide, ref, useSlots, watch } from 'vue';\nimport { useComponentId } from '../../composables/useComponentId';\nimport BSplitterPanel from './BSplitterPanel.vue';\nimport {\n BSplitterContextKey,\n type BSplitterCollapsible,\n type BSplitterOrientation,\n type BSplitterPanelCollapsible,\n type BSplitterPanelConfig,\n} from './types';\n\ndefineOptions({ name: 'BSplitter', inheritAttrs: false });\n\n/**\n * Internal helper component that renders an array of pre-built VNodes inside\n * a panel. Declared inline to keep the SFC self-contained.\n */\nconst VNodeRenderer = defineComponent({\n name: 'BSplitterVNodeRenderer',\n props: {\n nodes: {\n type: Array as PropType<VNode[] | undefined | null>,\n default: () => [],\n },\n },\n setup(props) {\n return () => (props.nodes && props.nodes.length ? h(Fragment, null, props.nodes) : null);\n },\n});\n\n//#region Props / Emits / Slots\nconst {\n vertical = false,\n orientation,\n lazy = false,\n collapsible: collapsibleConfig,\n} = defineProps<{\n /** Convenience boolean for vertical orientation. @default false */\n vertical?: boolean;\n /** Layout orientation. Takes precedence over `vertical` when set. */\n orientation?: BSplitterOrientation;\n /** Whether resize is committed only on release (preview line during drag). @default false */\n lazy?: boolean;\n /** Splitter-level collapsible config (motion + custom icons). */\n collapsible?: BSplitterCollapsible;\n}>();\n\nconst emit = defineEmits<{\n /** Fires while the user drags. Reports current pixel sizes of every panel. */\n resize: [sizes: number[]];\n /** Fires when the user starts dragging. */\n resizeStart: [sizes: number[]];\n /** Fires when the user releases the dragger. */\n resizeEnd: [sizes: number[]];\n /** Fires when a panel is collapsed/uncollapsed via a collapse button. */\n collapse: [collapsed: boolean[], sizes: number[]];\n /** Fires when the user double-clicks a dragger. Receives the dragger index. */\n draggerDoubleClick: [index: number];\n}>();\n\nconst slots = useSlots();\nconst { componentUID } = useComponentId();\n//#endregion\n\n//#region Orientation\nconst resolvedOrientation = computed<BSplitterOrientation>(() =>\n orientation ?? (vertical ? 'vertical' : 'horizontal'),\n);\nconst isVertical = computed(() => resolvedOrientation.value === 'vertical');\n\nprovide(BSplitterContextKey, {\n orientation: resolvedOrientation.value,\n});\n//#endregion\n\n//#region Slot inspection — extract panel configs from default slot\nfunction flattenChildren(children: VNode[]): VNode[] {\n const out: VNode[] = [];\n for (const vn of children) {\n if (vn.type === Fragment && Array.isArray(vn.children)) {\n out.push(...flattenChildren(vn.children as VNode[]));\n } else {\n out.push(vn);\n }\n }\n return out;\n}\n\nconst panelConfigs = computed<BSplitterPanelConfig[]>(() => {\n const raw = slots.default?.();\n if (!raw) return [];\n const flat = flattenChildren(raw);\n const result: BSplitterPanelConfig[] = [];\n let idx = 0;\n for (const vnode of flat) {\n if (vnode.type !== BSplitterPanel) continue;\n // Normalize prop keys to camelCase — Vue keeps the original (often\n // kebab-case) keys on the raw vnode.props.\n const rawProps = (vnode.props ?? {}) as Record<string, unknown>;\n const props: Record<string, unknown> = {};\n for (const k in rawProps) props[camelize(k)] = rawProps[k];\n\n const slotChildren = vnode.children as\n | { default?: () => VNode | VNode[] }\n | null\n | undefined;\n const rawDefault = slotChildren?.default?.();\n const content: VNode[] | undefined = rawDefault\n ? Array.isArray(rawDefault)\n ? rawDefault\n : [rawDefault]\n : undefined;\n\n let collapsible: BSplitterPanelCollapsible | false = false;\n const c = props.collapsible;\n if (c === true || c === '' || c === 'true') {\n collapsible = { start: true, end: true };\n } else if (c && typeof c === 'object') {\n collapsible = c as BSplitterPanelCollapsible;\n }\n\n const resizableRaw = props.resizable;\n const resizable =\n resizableRaw === undefined\n ? true\n : resizableRaw === false || resizableRaw === 'false'\n ? false\n : true;\n\n const destroyRaw = props.destroyOnHidden;\n const destroyOnHidden =\n destroyRaw === true || destroyRaw === '' || destroyRaw === 'true';\n\n result.push({\n index: idx++,\n size: props.size as number | string | undefined,\n defaultSize: props.defaultSize as number | string | undefined,\n min: props.min as number | string | undefined,\n max: props.max as number | string | undefined,\n resizable,\n collapsible,\n destroyOnHidden,\n content,\n });\n }\n return result;\n});\n//#endregion\n\n//#region Sizing internals\nconst rootRef = ref<HTMLElement | null>(null);\nconst containerSize = ref(0);\nconst DRAGGER_PX = 6; // matches --b-splitter-dragger-size default\n\n/** Pixel sizes for each panel, kept in sync with container size + props. */\nconst sizesPx = ref<number[]>([]);\n/** Per-panel collapsed flag (true → forced size 0). */\nconst collapsedFlags = ref<boolean[]>([]);\n/** Per-panel sizes saved before collapsing (so we can restore). */\nconst savedSizes = ref<(number | null)[]>([]);\n/**\n * Per-panel record of how it was collapsed:\n * - 'start': collapsed via the `<` button on the dragger AFTER the panel\n * (neighbor that absorbed = panel + 1)\n * - 'end': collapsed via the `>` button on the dragger BEFORE the panel\n * (neighbor that absorbed = panel - 1)\n * Used to decide which dragger should expose the restore button.\n */\nconst collapsedDirection = ref<('start' | 'end' | null)[]>([]);\n\nfunction parseLength(\n value: number | string | undefined,\n total: number,\n fallback = NaN,\n): number {\n if (value === undefined || value === null) return fallback;\n if (typeof value === 'number') return value;\n const s = value.trim();\n if (s.endsWith('%')) {\n const pct = parseFloat(s);\n return isFinite(pct) ? (pct / 100) * total : fallback;\n }\n if (s.endsWith('px')) return parseFloat(s);\n const n = parseFloat(s);\n return isFinite(n) ? n : fallback;\n}\n\nfunction availableSize(): number {\n const total = containerSize.value;\n const dividers = Math.max(panelConfigs.value.length - 1, 0) * DRAGGER_PX;\n return Math.max(total - dividers, 0);\n}\n\nfunction computeInitialSizes(): number[] {\n const panels = panelConfigs.value;\n const avail = availableSize();\n if (panels.length === 0 || avail <= 0) return panels.map(() => 0);\n\n const result: number[] = Array.from({ length: panels.length }, () => NaN);\n let assigned = 0;\n // First pass: explicit `size` and `defaultSize`.\n panels.forEach((p, i) => {\n const v = parseLength(p.size ?? p.defaultSize, avail);\n if (!isNaN(v)) {\n result[i] = v;\n assigned += v;\n }\n });\n // Distribute remainder evenly among the rest.\n const remainingIdx = result.map((v, i) => (isNaN(v) ? i : -1)).filter((i) => i >= 0);\n if (remainingIdx.length > 0) {\n const remainder = Math.max(avail - assigned, 0);\n const each = remainder / remainingIdx.length;\n remainingIdx.forEach((i) => (result[i] = each));\n }\n // Clamp to min/max and re-normalize so they sum to avail.\n return clampAndNormalize(result, avail);\n}\n\nfunction clampAndNormalize(input: number[], avail: number): number[] {\n const panels = panelConfigs.value;\n const out = input.map((v, i) => {\n const min = parseLength(panels[i]?.min, avail, 0);\n const max = parseLength(panels[i]?.max, avail, Infinity);\n return Math.min(Math.max(v, min), max);\n });\n // Normalize to fit avail.\n const sum = out.reduce((a, b) => a + b, 0);\n if (sum === 0 || avail === 0) return out;\n const scale = avail / sum;\n return out.map((v) => v * scale);\n}\n\nfunction syncFromProps() {\n const panels = panelConfigs.value;\n // Ensure collapsedFlags / savedSizes have correct length.\n if (collapsedFlags.value.length !== panels.length) {\n collapsedFlags.value = panels.map(() => false);\n savedSizes.value = panels.map(() => null);\n collapsedDirection.value = panels.map(() => null);\n }\n // Re-derive sizes when container or panel configs change.\n sizesPx.value = computeInitialSizes();\n}\n\n/**\n * Inspect controlled `size` props — when provided, reflect them into sizesPx.\n * AntD-style: when `size` is set, it acts as a controlled value.\n */\nwatch(\n () => panelConfigs.value.map((p) => `${p.size ?? ''}`).join('|'),\n () => {\n if (containerSize.value > 0) syncFromProps();\n },\n);\n\nwatch(\n () => panelConfigs.value.length,\n () => {\n if (containerSize.value > 0) syncFromProps();\n },\n);\n//#endregion\n\n//#region ResizeObserver — track container size\nlet resizeObserver: ResizeObserver | null = null;\n\nonMounted(() => {\n if (!rootRef.value) return;\n measureContainer();\n syncFromProps();\n if (typeof ResizeObserver !== 'undefined') {\n resizeObserver = new ResizeObserver(() => {\n const prev = containerSize.value;\n measureContainer();\n // Re-scale sizes proportionally on container resize.\n if (prev > 0 && containerSize.value > 0 && sizesPx.value.length > 0) {\n const ratio = availableSize() / Math.max(prev - DRAGGER_PX * (sizesPx.value.length - 1), 1);\n sizesPx.value = clampAndNormalize(\n sizesPx.value.map((v) => v * ratio),\n availableSize(),\n );\n } else {\n syncFromProps();\n }\n });\n resizeObserver.observe(rootRef.value);\n }\n});\n\nonBeforeUnmount(() => {\n resizeObserver?.disconnect();\n resizeObserver = null;\n removeDragListeners();\n});\n\nfunction measureContainer() {\n if (!rootRef.value) return;\n containerSize.value = isVertical.value\n ? rootRef.value.clientHeight\n : rootRef.value.clientWidth;\n}\n//#endregion\n\n//#region Dragging\ninterface DragState {\n draggerIndex: number;\n startCoord: number;\n startSizes: number[];\n /** In lazy mode, the preview offset (pixels relative to original divider). */\n previewDelta: number;\n}\nconst dragState = ref<DragState | null>(null);\nconst lazyPreviewDelta = ref<number | null>(null);\n\nfunction getCoord(e: MouseEvent | TouchEvent): number {\n if ('touches' in e) {\n const t = e.touches[0] ?? e.changedTouches[0];\n return isVertical.value ? t.clientY : t.clientX;\n }\n return isVertical.value ? e.clientY : e.clientX;\n}\n\nfunction onDraggerPointerDown(index: number, e: MouseEvent | TouchEvent) {\n if (!isResizable(index)) return;\n e.preventDefault();\n dragState.value = {\n draggerIndex: index,\n startCoord: getCoord(e),\n startSizes: [...sizesPx.value],\n previewDelta: 0,\n };\n lazyPreviewDelta.value = lazy ? 0 : null;\n emit('resizeStart', [...sizesPx.value]);\n\n document.addEventListener('mousemove', onDragMove);\n document.addEventListener('mouseup', onDragEnd);\n document.addEventListener('touchmove', onDragMove, { passive: false });\n document.addEventListener('touchend', onDragEnd);\n}\n\nfunction applyDelta(startSizes: number[], index: number, delta: number): number[] {\n const panels = panelConfigs.value;\n const avail = availableSize();\n const next = [...startSizes];\n const a = index;\n const b = index + 1;\n\n const aMin = parseLength(panels[a]?.min, avail, 0);\n const aMax = parseLength(panels[a]?.max, avail, Infinity);\n const bMin = parseLength(panels[b]?.min, avail, 0);\n const bMax = parseLength(panels[b]?.max, avail, Infinity);\n\n let newA = next[a] + delta;\n let newB = next[b] - delta;\n\n // Clamp so neither side violates its constraints.\n if (newA < aMin) {\n newB -= aMin - newA;\n newA = aMin;\n }\n if (newA > aMax) {\n newB += newA - aMax;\n newA = aMax;\n }\n if (newB < bMin) {\n newA -= bMin - newB;\n newB = bMin;\n }\n if (newB > bMax) {\n newA += newB - bMax;\n newB = bMax;\n }\n // Final clamp on `a` again in case `b` clamping pushed it out.\n newA = Math.min(Math.max(newA, aMin), aMax);\n newB = Math.min(Math.max(newB, bMin), bMax);\n next[a] = newA;\n next[b] = newB;\n return next;\n}\n\nfunction onDragMove(e: MouseEvent | TouchEvent) {\n if (!dragState.value) return;\n if ('touches' in e) e.preventDefault();\n const coord = getCoord(e);\n const delta = coord - dragState.value.startCoord;\n\n if (lazy) {\n // Update preview indicator only.\n lazyPreviewDelta.value = delta;\n return;\n }\n const next = applyDelta(dragState.value.startSizes, dragState.value.draggerIndex, delta);\n sizesPx.value = next;\n emit('resize', [...next]);\n}\n\nfunction onDragEnd(e: MouseEvent | TouchEvent) {\n if (!dragState.value) return;\n const coord = 'changedTouches' in e ? getCoord(e) : getCoord(e);\n const delta = coord - dragState.value.startCoord;\n\n if (lazy) {\n const next = applyDelta(dragState.value.startSizes, dragState.value.draggerIndex, delta);\n sizesPx.value = next;\n emit('resize', [...next]);\n }\n emit('resizeEnd', [...sizesPx.value]);\n dragState.value = null;\n lazyPreviewDelta.value = null;\n removeDragListeners();\n}\n\nfunction removeDragListeners() {\n document.removeEventListener('mousemove', onDragMove);\n document.removeEventListener('mouseup', onDragEnd);\n document.removeEventListener('touchmove', onDragMove);\n document.removeEventListener('touchend', onDragEnd);\n}\n\nfunction isResizable(draggerIndex: number): boolean {\n const a = panelConfigs.value[draggerIndex];\n const b = panelConfigs.value[draggerIndex + 1];\n return !!(a?.resizable && b?.resizable);\n}\n\nfunction onDraggerDoubleClick(i: number) {\n emit('draggerDoubleClick', i);\n}\n//#endregion\n\n//#region Keyboard\nconst KEY_STEP = 10;\n\nfunction onDraggerKeyDown(index: number, e: KeyboardEvent) {\n if (!isResizable(index)) return;\n let delta = 0;\n switch (e.key) {\n case 'ArrowLeft':\n delta = isVertical.value ? 0 : -KEY_STEP;\n break;\n case 'ArrowRight':\n delta = isVertical.value ? 0 : KEY_STEP;\n break;\n case 'ArrowUp':\n delta = isVertical.value ? -KEY_STEP : 0;\n break;\n case 'ArrowDown':\n delta = isVertical.value ? KEY_STEP : 0;\n break;\n case 'Home': {\n // collapse the panel before the dragger to its minimum.\n const avail = availableSize();\n const a = panelConfigs.value[index];\n delta = -(sizesPx.value[index] - parseLength(a?.min, avail, 0));\n break;\n }\n case 'End': {\n const avail = availableSize();\n const b = panelConfigs.value[index + 1];\n delta = sizesPx.value[index + 1] - parseLength(b?.min, avail, 0);\n break;\n }\n case 'Enter':\n case ' ':\n // Toggle: collapse the smaller adjacent panel toward the larger one.\n e.preventDefault();\n toggleCollapseAtDragger(index);\n return;\n default:\n return;\n }\n if (delta === 0) return;\n e.preventDefault();\n emit('resizeStart', [...sizesPx.value]);\n const next = applyDelta(sizesPx.value, index, delta);\n sizesPx.value = next;\n emit('resize', [...next]);\n emit('resizeEnd', [...next]);\n}\n//#endregion\n\n//#region Collapse / Expand\nfunction toggleCollapseAtDragger(index: number) {\n // Default keyboard behaviour: collapse the start side if it has more room than 0.\n const a = panelConfigs.value[index];\n const b = panelConfigs.value[index + 1];\n if (a?.collapsible) collapsePanel(index, 'start');\n else if (b?.collapsible) collapsePanel(index + 1, 'end');\n}\n\n/**\n * Collapse a panel toward the previous (`'start'`) or next (`'end'`) panel.\n * If already collapsed, restore the saved size.\n */\nfunction collapsePanel(panelIndex: number, direction: 'start' | 'end') {\n const panel = panelConfigs.value[panelIndex];\n if (!panel) return;\n const avail = availableSize();\n const sizes = [...sizesPx.value];\n\n // The neighbor that absorbs / returns the collapsed panel's space.\n // - direction='start': panel collapses toward start ⇒ space goes to panelIndex + 1\n // - direction='end': panel collapses toward end ⇒ space goes to panelIndex - 1\n const neighbor = direction === 'start' ? panelIndex + 1 : panelIndex - 1;\n\n if (collapsedFlags.value[panelIndex]) {\n // Restore: take saved size back from the same neighbor that absorbed it.\n const saved = savedSizes.value[panelIndex] ?? avail / panelConfigs.value.length;\n if (neighbor >= 0 && neighbor < sizes.length) {\n const give = Math.min(saved, sizes[neighbor]);\n sizes[panelIndex] = give;\n sizes[neighbor] -= give;\n } else {\n sizes[panelIndex] = saved;\n }\n collapsedFlags.value = collapsedFlags.value.map((v, i) => (i === panelIndex ? false : v));\n savedSizes.value = savedSizes.value.map((v, i) => (i === panelIndex ? null : v));\n collapsedDirection.value = collapsedDirection.value.map((v, i) =>\n i === panelIndex ? null : v,\n );\n } else {\n // Collapse: dump current size into the neighbor.\n savedSizes.value = savedSizes.value.map((v, i) =>\n i === panelIndex ? sizes[panelIndex] : v,\n );\n if (neighbor >= 0 && neighbor < sizes.length) {\n sizes[neighbor] += sizes[panelIndex];\n }\n sizes[panelIndex] = 0;\n collapsedFlags.value = collapsedFlags.value.map((v, i) => (i === panelIndex ? true : v));\n collapsedDirection.value = collapsedDirection.value.map((v, i) =>\n i === panelIndex ? direction : v,\n );\n }\n sizesPx.value = sizes;\n emit('resize', [...sizes]);\n emit('resizeEnd', [...sizes]);\n emit('collapse', [...collapsedFlags.value], [...sizes]);\n}\n\n/**\n * Helpers for the two collapse buttons rendered on each dragger between\n * panel `i` (prev) and panel `i + 1` (next). Mirrors AntD's logic:\n * the START (`<`) button can either collapse prev or expand a previously-\n * collapsed next; the END (`>`) button is symmetric.\n */\nfunction startBtnPanelCfg(i: number) {\n return panelConfigs.value[i]?.collapsible\n ? (panelConfigs.value[i].collapsible as BSplitterPanelCollapsible)\n : null;\n}\nfunction endBtnPanelCfg(i: number) {\n return panelConfigs.value[i + 1]?.collapsible\n ? (panelConfigs.value[i + 1].collapsible as BSplitterPanelCollapsible)\n : null;\n}\nfunction canShowStartBtn(i: number): boolean {\n const sizes = sizesPx.value;\n const prevSize = sizes[i] ?? 0;\n const nextSize = sizes[i + 1] ?? 0;\n // Mode A — collapse prev (panel i).\n const prevCfg = startBtnPanelCfg(i);\n const collapsePrev = !!prevCfg?.start && prevSize > 0 && nextSize > 0;\n // Mode B — restore next (panel i + 1) if it was collapsed via THIS dragger.\n const restoreNext =\n !!collapsedFlags.value[i + 1] &&\n collapsedDirection.value[i + 1] === 'end' &&\n prevSize > 0;\n return collapsePrev || restoreNext;\n}\nfunction canShowEndBtn(i: number): boolean {\n const sizes = sizesPx.value;\n const prevSize = sizes[i] ?? 0;\n const nextSize = sizes[i + 1] ?? 0;\n // Mode A — collapse next (panel i + 1).\n const nextCfg = endBtnPanelCfg(i);\n const collapseNext = !!nextCfg?.end && nextSize > 0 && prevSize > 0;\n // Mode B — restore prev (panel i) if it was collapsed via THIS dragger.\n const restorePrev =\n !!collapsedFlags.value[i] &&\n collapsedDirection.value[i] === 'start' &&\n nextSize > 0;\n return collapseNext || restorePrev;\n}\nfunction onClickStartBtn(i: number) {\n if (\n collapsedFlags.value[i + 1] &&\n collapsedDirection.value[i + 1] === 'end'\n ) {\n // Restore next, taking space back from prev.\n collapsePanel(i + 1, 'end');\n } else {\n collapsePanel(i, 'start');\n }\n}\nfunction onClickEndBtn(i: number) {\n if (collapsedFlags.value[i] && collapsedDirection.value[i] === 'start') {\n // Restore prev, taking space back from next.\n collapsePanel(i, 'start');\n } else {\n collapsePanel(i + 1, 'end');\n }\n}\nfunction startBtnAriaLabel(i: number): string {\n if (\n collapsedFlags.value[i + 1] &&\n collapsedDirection.value[i + 1] === 'end'\n ) {\n return `Expand panel ${i + 2}`;\n }\n return `Collapse panel ${i + 1}`;\n}\nfunction endBtnAriaLabel(i: number): string {\n if (collapsedFlags.value[i] && collapsedDirection.value[i] === 'start') {\n return `Expand panel ${i + 1}`;\n }\n return `Collapse panel ${i + 2}`;\n}\n//#endregion\n\n//#region Style helpers\nconst motion = computed(() => collapsibleConfig?.motion !== false);\n\nfunction panelStyle(i: number): CSSProperties {\n const sz = sizesPx.value[i] ?? 0;\n const sizeStr = `${sz}px`;\n return isVertical.value\n ? { height: sizeStr, flex: `0 0 ${sizeStr}` }\n : { width: sizeStr, flex: `0 0 ${sizeStr}` };\n}\n\nfunction draggerAriaValueNow(i: number): number {\n const avail = availableSize();\n if (avail === 0) return 0;\n const accumulated = sizesPx.value.slice(0, i + 1).reduce((a, b) => a + b, 0);\n return Math.round((accumulated / avail) * 100);\n}\n\nconst lazyIndicatorStyle = computed<CSSProperties | undefined>(() => {\n if (!lazy || !dragState.value || lazyPreviewDelta.value === null) return undefined;\n const idx = dragState.value.draggerIndex;\n const before = dragState.value.startSizes.slice(0, idx + 1).reduce((a, b) => a + b, 0);\n const offset = before + idx * DRAGGER_PX + lazyPreviewDelta.value;\n return isVertical.value ? { top: `${offset}px` } : { left: `${offset}px` };\n});\n//#endregion\n\n//#region Expose\nfunction getSizes(): number[] {\n return [...sizesPx.value];\n}\nfunction setSizes(next: number[]) {\n if (next.length !== sizesPx.value.length) return;\n sizesPx.value = clampAndNormalize(next, availableSize());\n emit('resize', [...sizesPx.value]);\n}\ndefineExpose({ getSizes, setSizes });\n//#endregion\n\n//#region Render-time per-panel render helper\n/**\n * Returns the panel's slot content as VNodes, honoring `destroyOnHidden`.\n */\nfunction panelContent(panel: BSplitterPanelConfig, i: number): VNode[] | null {\n const collapsed = (sizesPx.value[i] ?? 0) <= 0;\n if (panel.destroyOnHidden && collapsed) return null;\n return panel.content ?? null;\n}\n//#endregion\n</script>\n\n<template>\n <div\n ref=\"rootRef\"\n class=\"b-splitter\"\n :class=\"{\n 'b-splitter--horizontal': !isVertical,\n 'b-splitter--vertical': isVertical,\n 'b-splitter--lazy': lazy,\n 'b-splitter--motion': motion,\n 'b-splitter--dragging': dragState !== null,\n }\"\n :data-orientation=\"resolvedOrientation\"\n >\n <template v-for=\"(panel, i) in panelConfigs\" :key=\"`panel-${componentUID}-${i}`\">\n <div\n :id=\"`b-splitter-${componentUID}-panel-${i}`\"\n class=\"b-splitter__panel\"\n :class=\"{ 'b-splitter__panel--collapsed': (sizesPx[i] ?? 0) <= 0 }\"\n :style=\"panelStyle(i)\"\n role=\"group\"\n >\n <component :is=\"VNodeRenderer\" :nodes=\"panelContent(panel, i)\" />\n </div>\n\n <!-- Divider wrapper holds the dragger + collapse buttons as siblings\n so we don't nest interactive controls (a11y: nested-interactive). -->\n <div\n v-if=\"i < panelConfigs.length - 1\"\n class=\"b-splitter__divider\"\n :class=\"{ 'b-splitter__divider--disabled': !isResizable(i) }\"\n >\n <div\n class=\"b-splitter__dragger\"\n :class=\"{\n 'b-splitter__dragger--disabled': !isResizable(i),\n 'b-splitter__dragger--active': dragState && dragState.draggerIndex === i,\n }\"\n role=\"separator\"\n :tabindex=\"isResizable(i) ? 0 : -1\"\n :aria-orientation=\"isVertical ? 'horizontal' : 'vertical'\"\n :aria-controls=\"`b-splitter-${componentUID}-panel-${i} b-splitter-${componentUID}-panel-${i + 1}`\"\n :aria-valuenow=\"draggerAriaValueNow(i)\"\n aria-valuemin=\"0\"\n aria-valuemax=\"100\"\n :aria-disabled=\"!isResizable(i) || undefined\"\n :aria-label=\"`Resize panel ${i + 1}`\"\n @mousedown=\"onDraggerPointerDown(i, $event)\"\n @touchstart=\"onDraggerPointerDown(i, $event)\"\n @keydown=\"onDraggerKeyDown(i, $event)\"\n @dblclick=\"onDraggerDoubleClick(i)\"\n >\n <span aria-hidden=\"true\" class=\"b-splitter__handle\">\n <slot name=\"draggerIcon\" />\n </span>\n </div>\n\n <!--\n Collapse \"start\" button (LEFT half of dragger). Two modes:\n - Collapse prev (panel i) when prev is visible.\n - Restore next (panel i + 1) when next was collapsed via the `>`\n button on THIS dragger.\n -->\n <button\n v-if=\"canShowStartBtn(i)\"\n type=\"button\"\n class=\"b-splitter__collapse-btn b-splitter__collapse-btn--start\"\n :aria-label=\"startBtnAriaLabel(i)\"\n :aria-expanded=\"\n collapsedFlags[i + 1] && collapsedDirection[i + 1] === 'end'\n ? false\n : true\n \"\n @mousedown.stop\n @touchstart.stop\n @click.stop=\"onClickStartBtn(i)\"\n >\n <slot name=\"collapseIconStart\">\n <svg\n aria-hidden=\"true\"\n class=\"b-splitter__chevron b-splitter__chevron--start\"\n viewBox=\"0 0 8 8\"\n width=\"8\"\n height=\"8\"\n >\n <polyline\n points=\"5,1 2,4 5,7\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n\n <!--\n Collapse \"end\" button (RIGHT half of dragger). Two modes:\n - Collapse next (panel i + 1) when next is visible.\n - Restore prev (panel i) when prev was collapsed via the `<`\n button on THIS dragger.\n -->\n <button\n v-if=\"canShowEndBtn(i)\"\n type=\"button\"\n class=\"b-splitter__collapse-btn b-splitter__collapse-btn--end\"\n :aria-label=\"endBtnAriaLabel(i)\"\n :aria-expanded=\"\n collapsedFlags[i] && collapsedDirection[i] === 'start'\n ? false\n : true\n \"\n @mousedown.stop\n @touchstart.stop\n @click.stop=\"onClickEndBtn(i)\"\n >\n <slot name=\"collapseIconEnd\">\n <svg\n aria-hidden=\"true\"\n class=\"b-splitter__chevron b-splitter__chevron--end\"\n viewBox=\"0 0 8 8\"\n width=\"8\"\n height=\"8\"\n >\n <polyline\n points=\"3,1 6,4 3,7\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n </slot>\n </button>\n </div>\n </template>\n\n <!-- Lazy preview indicator -->\n <div\n v-if=\"lazy && dragState && lazyPreviewDelta !== null\"\n class=\"b-splitter__lazy-indicator\"\n :style=\"lazyIndicatorStyle\"\n aria-hidden=\"true\"\n />\n </div>\n</template>\n\n<style>\n.b-splitter {\n /* Component design tokens (AntD parity) */\n --b-splitter-split-bar-size: 2px;\n --b-splitter-dragger-size: 6px;\n --b-splitter-dragger-draggable-size: 20px;\n --b-splitter-bg: oklch(94% 0 0); /* colorFill */\n --b-splitter-bg-hover: oklch(85% 0 0); /* colorFillSecondary */\n --b-splitter-bg-active: oklch(60% 0.18 264); /* colorPrimary */\n --b-splitter-text-color: oklch(40% 0 0);\n --b-splitter-color-bg-elevated: #fff;\n --b-splitter-collapse-bar-bg: oklch(94% 0 0);\n --b-splitter-collapse-bar-bg-hover: oklch(60% 0.18 264);\n --b-splitter-collapse-icon-color: oklch(60% 0 0);\n --b-splitter-collapse-icon-color-hover: #fff;\n --b-splitter-motion-duration: 0.2s;\n --b-splitter-z-index-base: 1;\n\n position: relative;\n display: flex;\n width: 100%;\n height: 100%;\n min-height: 0;\n min-width: 0;\n}\n\n.b-splitter--horizontal {\n flex-direction: row;\n}\n.b-splitter--vertical {\n flex-direction: column;\n}\n\n/* Panel */\n.b-splitter__panel {\n position: relative;\n overflow: auto;\n min-width: 0;\n min-height: 0;\n box-sizing: border-box;\n}\n.b-splitter--motion .b-splitter__panel {\n transition:\n width var(--b-splitter-motion-duration) ease,\n height var(--b-splitter-motion-duration) ease,\n flex-basis var(--b-splitter-motion-duration) ease;\n}\n.b-splitter--dragging .b-splitter__panel {\n transition: none;\n}\n.b-splitter__panel--collapsed {\n overflow: hidden;\n}\n\n/* Divider — non-interactive wrapper holding the dragger + collapse buttons.\n It is the flex item that occupies the dragger size; the dragger and the\n collapse buttons sit inside as siblings (avoids nested-interactive a11y\n violation). */\n.b-splitter__divider {\n position: relative;\n flex: 0 0 var(--b-splitter-dragger-size);\n align-self: stretch;\n box-sizing: border-box;\n z-index: var(--b-splitter-z-index-base);\n}\n.b-splitter--horizontal .b-splitter__divider {\n width: var(--b-splitter-dragger-size);\n height: 100%;\n}\n.b-splitter--vertical .b-splitter__divider {\n width: 100%;\n height: var(--b-splitter-dragger-size);\n}\n\n/* Dragger — fills the divider and is the focusable separator. */\n.b-splitter__dragger {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n background: transparent;\n outline: none;\n box-sizing: border-box;\n user-select: none;\n touch-action: none;\n}\n.b-splitter--horizontal .b-splitter__dragger {\n cursor: col-resize;\n}\n.b-splitter--vertical .b-splitter__dragger {\n cursor: row-resize;\n}\n.b-splitter__dragger--disabled {\n cursor: default;\n}\n\n/* Visible bar via ::before — sits in centre of dragger */\n.b-splitter__dragger::before {\n content: '';\n position: absolute;\n background: var(--b-splitter-bg);\n border-radius: 2px;\n transition: background var(--b-splitter-motion-duration) ease;\n}\n.b-splitter--horizontal .b-splitter__dragger::before {\n top: 0;\n bottom: 0;\n left: calc(50% - var(--b-splitter-split-bar-size) / 2);\n width: var(--b-splitter-split-bar-size);\n}\n.b-splitter--vertical .b-splitter__dragger::before {\n left: 0;\n right: 0;\n top: calc(50% - var(--b-splitter-split-bar-size) / 2);\n height: var(--b-splitter-split-bar-size);\n}\n.b-splitter__dragger:not(.b-splitter__dragger--disabled):hover::before,\n.b-splitter__dragger:focus-visible::before,\n.b-splitter__dragger--active::before {\n background: var(--b-splitter-bg-active);\n}\n\n/* Visible draggable indicator (grip) — `splitBarDraggableSize` long, slightly\n thicker than the split bar to give the user a clear hit-target hint. */\n.b-splitter__dragger::after {\n content: '';\n position: absolute;\n background: var(--b-splitter-bg);\n border-radius: 2px;\n pointer-events: none;\n transition: background var(--b-splitter-motion-duration) ease;\n}\n.b-splitter--horizontal .b-splitter__dragger::after {\n width: 4px;\n height: var(--b-splitter-dragger-draggable-size);\n top: calc(50% - var(--b-splitter-dragger-draggable-size) / 2);\n left: calc(50% - 2px);\n}\n.b-splitter--vertical .b-splitter__dragger::after {\n width: var(--b-splitter-dragger-draggable-size);\n height: 4px;\n left: calc(50% - var(--b-splitter-dragger-draggable-size) / 2);\n top: calc(50% - 2px);\n}\n.b-splitter__dragger--disabled::after {\n display: none;\n}\n.b-splitter__dragger:not(.b-splitter__dragger--disabled):hover::after,\n.b-splitter__dragger:focus-visible::after,\n.b-splitter__dragger--active::after {\n background: var(--b-splitter-bg-active);\n}\n\n.b-splitter__dragger:focus-visible {\n outline: 2px solid var(--b-splitter-bg-active);\n outline-offset: -2px;\n}\n\n/* Drag handle (decorative) */\n.b-splitter__handle {\n position: absolute;\n inset: 0;\n display: flex;\n align-items: center;\n justify-content: center;\n pointer-events: none;\n}\n\n/* Collapse button */\n.b-splitter__collapse-btn {\n position: absolute;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 14px;\n height: 18px;\n padding: 0;\n border: none;\n border-radius: 2px;\n background: var(--b-splitter-collapse-bar-bg);\n color: var(--b-splitter-collapse-icon-color);\n cursor: pointer;\n transition:\n background var(--b-splitter-motion-duration) ease,\n color var(--b-splitter-motion-duration) ease;\n z-index: calc(var(--b-splitter-z-index-base) + 1);\n}\n.b-splitter__collapse-btn:hover,\n.b-splitter__collapse-btn:focus-visible {\n background: var(--b-splitter-collapse-bar-bg-hover);\n color: var(--b-splitter-collapse-icon-color-hover);\n}\n.b-splitter__collapse-btn:focus-visible {\n outline: 2px solid var(--b-splitter-bg-active);\n outline-offset: 1px;\n}\n.b-splitter--horizontal .b-splitter__collapse-btn--start,\n.b-splitter--horizontal .b-splitter__collapse-btn--end {\n top: 50%;\n transform: translateY(-50%);\n}\n.b-splitter--horizontal .b-splitter__collapse-btn--start {\n right: calc(50% + 2px);\n}\n.b-splitter--horizontal .b-splitter__collapse-btn--end {\n left: calc(50% + 2px);\n}\n.b-splitter--vertical .b-splitter__collapse-btn {\n width: 18px;\n height: 14px;\n}\n.b-splitter--vertical .b-splitter__collapse-btn--start,\n.b-splitter--vertical .b-splitter__collapse-btn--end {\n left: 50%;\n transform: translateX(-50%);\n}\n.b-splitter--vertical .b-splitter__collapse-btn--start {\n bottom: calc(50% + 2px);\n}\n.b-splitter--vertical .b-splitter__collapse-btn--end {\n top: calc(50% + 2px);\n}\n\n/* Chevron icon (SVG) */\n.b-splitter__chevron {\n display: block;\n width: 8px;\n height: 8px;\n}\n.b-splitter--vertical .b-splitter__chevron--start {\n transform: rotate(90deg);\n}\n.b-splitter--vertical .b-splitter__chevron--end {\n transform: rotate(-90deg);\n}\n\n/* Lazy preview indicator */\n.b-splitter__lazy-indicator {\n position: absolute;\n background: var(--b-splitter-bg-active);\n pointer-events: none;\n z-index: calc(var(--b-splitter-z-index-base) + 2);\n}\n.b-splitter--horizontal .b-splitter__lazy-indicator {\n top: 0;\n bottom: 0;\n width: var(--b-splitter-split-bar-size);\n}\n.b-splitter--vertical .b-splitter__lazy-indicator {\n left: 0;\n right: 0;\n height: var(--b-splitter-split-bar-size);\n}\n\n/* Dark mode — reassign tokens, no new vars */\n[data-prefers-color='dark'] .b-splitter {\n --b-splitter-bg: oklch(30% 0 0);\n --b-splitter-bg-hover: oklch(40% 0 0);\n --b-splitter-bg-active: oklch(70% 0.18 264);\n --b-splitter-text-color: oklch(85% 0 0);\n --b-splitter-color-bg-elevated: oklch(20% 0 0);\n --b-splitter-collapse-bar-bg: oklch(30% 0 0);\n --b-splitter-collapse-bar-bg-hover: oklch(70% 0.18 264);\n --b-splitter-collapse-icon-color: oklch(70% 0 0);\n --b-splitter-collapse-icon-color-hover: oklch(15% 0 0);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-splitter {\n --b-splitter-bg: oklch(30% 0 0);\n --b-splitter-bg-hover: oklch(40% 0 0);\n --b-splitter-bg-active: oklch(70% 0.18 264);\n --b-splitter-text-color: oklch(85% 0 0);\n --b-splitter-color-bg-elevated: oklch(20% 0 0);\n --b-splitter-collapse-bar-bg: oklch(30% 0 0);\n --b-splitter-collapse-bar-bg-hover: oklch(70% 0.18 264);\n --b-splitter-collapse-icon-color: oklch(70% 0 0);\n --b-splitter-collapse-icon-color-hover: oklch(15% 0 0);\n }\n}\n\n/* Reduced motion */\n@media (prefers-reduced-motion: reduce) {\n .b-splitter__panel,\n .b-splitter__dragger::before,\n .b-splitter__collapse-btn {\n transition: none !important;\n }\n}\n</style>\n"],"mappings":""}
@@ -1,8 +1,111 @@
1
- import e from "./design-system205.js";
2
- /* empty css */
3
- //#region src/components/BTimeline/BTimeline.vue
4
- var t = e;
1
+ import { BCommonSize as e, BIconSize as t, BStepsDirection as n, BStepsLabelPlacement as r, BStepsStatus as i, BStepsType as a } from "./design-system3.js";
2
+ import o from "./design-system27.js";
3
+ import { Fragment as s, computed as c, createBlock as l, createCommentVNode as u, createElementBlock as d, createElementVNode as f, defineComponent as p, mergeModels as m, normalizeClass as h, normalizeStyle as g, openBlock as _, renderList as v, toDisplayString as y, toRefs as b, unref as x, useModel as S } from "vue";
4
+ //#region src/components/BSteps/BSteps.vue?vue&type=script&setup=true&lang.ts
5
+ var C = ["data-status"], w = [
6
+ "role",
7
+ "tabindex",
8
+ "aria-disabled",
9
+ "aria-current",
10
+ "onClick",
11
+ "onKeydown"
12
+ ], T = { class: "b:flex b:items-center b:gap-x-2" }, E = {
13
+ key: 0,
14
+ "aria-hidden": "true",
15
+ class: "b-steps__tail"
16
+ }, D = /* @__PURE__ */ p({
17
+ __name: "BSteps",
18
+ props: /* @__PURE__ */ m({
19
+ items: { default: () => [] },
20
+ status: { default: i.Process },
21
+ direction: { default: n.Horizontal },
22
+ size: { default: e.Medium },
23
+ labelPlacement: { default: r.Horizontal },
24
+ type: { default: a.Default }
25
+ }, {
26
+ modelValue: { default: 0 },
27
+ modelModifiers: {}
28
+ }),
29
+ emits: /* @__PURE__ */ m(["change"], ["update:modelValue"]),
30
+ setup(p, { emit: m }) {
31
+ let { items: D, status: O, direction: k, size: A, labelPlacement: j, type: M } = b(p), N = S(p, "modelValue"), P = m, F = c(() => A.value === e.Small ? e.Small : e.Medium), I = c(() => F.value === e.Small ? t.Small : t.Medium), L = c(() => ({
32
+ "--b-steps-icon-size": F.value === e.Small ? "1.5rem" : "2rem",
33
+ "--b-steps-gap": F.value === e.Small ? "0.5rem" : "0.75rem"
34
+ })), R = c(() => F.value === e.Small ? "b:text-sm" : "b:text-base"), z = c(() => F.value === e.Small ? "b:text-xs" : "b:text-sm"), B = c(() => M.value === a.Navigation), V = (e, t) => e.status ? e.status : t === N.value ? O.value || i.Process : t < N.value ? i.Finish : i.Wait, H = (e) => {
35
+ switch (e) {
36
+ case i.Finish:
37
+ case i.Process: return "var(--b-color-primary)";
38
+ case i.Error: return "var(--b-color-failure)";
39
+ case i.Wait:
40
+ default: return "var(--b-color-zinc-200)";
41
+ }
42
+ }, U = (e, t) => {
43
+ !B.value || e.disabled || (N.value = t, P("change", t));
44
+ }, W = (e, t, n) => {
45
+ (e.key === "Enter" || e.key === " ") && (e.preventDefault(), U(t, n));
46
+ }, G = (e) => ({
47
+ "b:border-secondary b:bg-white b:text-secondary": e === i.Wait,
48
+ "b:border-primary b:bg-primary b:text-white": e === i.Process,
49
+ "b:border-primary b:bg-white b:text-primary": e === i.Finish,
50
+ "b:border-failure b:bg-white b:text-failure": e === i.Error
51
+ }), K = (e) => ({
52
+ "b:text-black-base": e === i.Process || e === i.Finish,
53
+ "b:text-failure": e === i.Error,
54
+ "b:text-black/65": e === i.Wait
55
+ }), q = (e) => ({
56
+ "b:text-black/65": e !== i.Error,
57
+ "b:text-failure": e === i.Error
58
+ });
59
+ return (t, c) => (_(), d("ol", {
60
+ class: h(["b-steps", [{
61
+ "b-steps--horizontal": x(k) === x(n).Horizontal,
62
+ "b-steps--vertical": x(k) === x(n).Vertical,
63
+ "b-steps--label-vertical": x(k) === x(n).Horizontal && x(j) === x(r).Vertical,
64
+ "b-steps--navigation": x(M) === x(a).Navigation,
65
+ "b-steps--inline": x(M) === x(a).Inline
66
+ }]]),
67
+ style: g(L.value)
68
+ }, [(_(!0), d(s, null, v(x(D), (t, a) => (_(), d("li", {
69
+ key: `${t.title}-${a}`,
70
+ class: h(["b-steps__item", [{ "b:opacity-50": t.disabled }, { "b-steps__item--clickable": B.value && !t.disabled }]]),
71
+ "data-status": V(t, a),
72
+ style: g({ "--b-steps-tail-color": H(V(t, a)) })
73
+ }, [f("div", {
74
+ class: "b-steps__item-inner",
75
+ role: B.value && !t.disabled ? "button" : void 0,
76
+ tabindex: B.value && !t.disabled ? 0 : void 0,
77
+ "aria-disabled": t.disabled ? "true" : void 0,
78
+ "aria-current": a === N.value ? "step" : void 0,
79
+ onClick: (e) => U(t, a),
80
+ onKeydown: (e) => W(e, t, a)
81
+ }, [f("div", { class: h(["b-steps__icon b:flex b:items-center b:justify-center b:rounded-full b:border", [G(V(t, a)), {
82
+ "b:h-6 b:w-6": F.value === x(e).Small,
83
+ "b:h-8 b:w-8": F.value === x(e).Medium
84
+ }]]) }, [t.icon ? (_(), l(o, {
85
+ key: 0,
86
+ icon: t.icon,
87
+ size: I.value
88
+ }, null, 8, ["icon", "size"])) : V(t, a) === x(i).Finish ? (_(), l(o, {
89
+ key: 1,
90
+ icon: "check",
91
+ size: I.value
92
+ }, null, 8, ["size"])) : V(t, a) === x(i).Error ? (_(), l(o, {
93
+ key: 2,
94
+ icon: "xmark",
95
+ size: I.value
96
+ }, null, 8, ["size"])) : (_(), d("span", {
97
+ key: 3,
98
+ class: h(R.value)
99
+ }, y(a + 1), 3))], 2), f("div", { class: h(["b-steps__content b:flex b:flex-col b:gap-y-1", [{ "b:items-center b:text-center": x(k) === x(n).Horizontal && x(j) === x(r).Vertical }]]) }, [f("div", T, [f("span", { class: h(["b:font-medium", [R.value, K(V(t, a))]]) }, y(t.title), 3), t.subTitle ? (_(), d("span", {
100
+ key: 0,
101
+ class: h(["b:text-xs b:text-black/65", K(V(t, a))])
102
+ }, y(t.subTitle), 3)) : u("", !0)]), t.description ? (_(), d("p", {
103
+ key: 0,
104
+ class: h(["b:leading-snug", [z.value, q(V(t, a))]])
105
+ }, y(t.description), 3)) : u("", !0)], 2)], 40, w), x(k) === x(n).Horizontal && a < x(D).length - 1 ? (_(), d("span", E)) : u("", !0)], 14, C))), 128))], 6));
106
+ }
107
+ });
5
108
  //#endregion
6
- export { t as default };
109
+ export { D as default };
7
110
 
8
111
  //# sourceMappingURL=design-system207.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"design-system207.js","names":[],"sources":["../src/components/BTimeline/BTimeline.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, provide } from 'vue';\n\nimport type {\n BTimelineItem,\n BTimelineItemColor,\n BTimelineItemPlacement,\n BTimelineMode,\n BTimelineOrientation,\n BTimelineVariant,\n} from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n mode = 'start',\n variant = 'filled',\n orientation = 'vertical',\n pending = false,\n pendingDot,\n reverse = false,\n items,\n} = defineProps<{\n /**\n * Controls which side labels appear on.\n * - `'start'` - all content on the right of the line (default)\n * - `'end'` - all content on the left of the line\n * - `'alternate'` - content alternates left/right\n * @default 'start'\n */\n mode?: BTimelineMode;\n /**\n * Dot style.\n * - `'filled'` - solid filled circle (default)\n * - `'outlined'` - hollow ring with colored border\n * @default 'filled'\n */\n variant?: BTimelineVariant;\n /**\n * Layout direction.\n * - `'vertical'` - items stacked top-to-bottom (default)\n * - `'horizontal'` - items laid out left-to-right\n * @default 'vertical'\n */\n orientation?: BTimelineOrientation;\n /**\n * Whether to show a pending (ghost) item at the bottom.\n * Pass `true` for the default spinner, or a string for custom content.\n * @default false\n */\n pending?: boolean | string;\n /**\n * Custom dot for the pending item. Overridden by the `#pendingDot` slot.\n */\n pendingDot?: string;\n /**\n * Whether to reverse the order of items (newest first).\n * @default false\n */\n reverse?: boolean;\n /**\n * Data-driven items. When provided, slot-based BTimelineItem children are\n * ignored. Use this for simple, data-only timelines.\n */\n items?: BTimelineItem[];\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /**\n * Default slot: place `<BTimelineItem>` children here.\n * Ignored when `items` prop is provided.\n */\n default?(): unknown;\n /** Custom dot for the pending ghost item. */\n pendingDot?(): unknown;\n}>();\n\n// Provide mode to slot-based BTimelineItem children\nprovide('b-timeline-mode', mode);\nprovide('b-timeline-variant', variant);\n\n// ─────────────────────────────────────────────\n// Pending item helpers\n// ─────────────────────────────────────────────\nconst hasPending = computed(() => !!pending);\nconst pendingContent = computed(() => (pending !== true && pending ? pending : ''));\n\n// ─────────────────────────────────────────────\n// Reversed items (data-driven)\n// ─────────────────────────────────────────────\nconst orderedItems = computed<BTimelineItem[]>(() => {\n if (!items) return [];\n return reverse ? [...items].reverse() : items;\n});\n\n// ─────────────────────────────────────────────\n// CSS-var dot color helper\n// ─────────────────────────────────────────────\nconst PRESET_COLORS: BTimelineItemColor[] = ['blue', 'red', 'green', 'gray'];\n\nfunction isPresetColor(color?: BTimelineItemColor): boolean {\n return !color || PRESET_COLORS.includes(color as string);\n}\n\nfunction dotColorStyle(color?: BTimelineItemColor): Record<string, string> | undefined {\n if (!color || isPresetColor(color)) return undefined;\n return { '--b-timeline-item-dot-color': color };\n}\n\nfunction dotColorClass(color?: BTimelineItemColor): string {\n const c = color ?? 'blue';\n return isPresetColor(c) ? `b-timeline-item--${c}` : 'b-timeline-item--custom';\n}\n\n// ─────────────────────────────────────────────\n// Root classes\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-timeline',\n `b-timeline--${mode}`,\n `b-timeline--${variant}`,\n `b-timeline--${orientation}`,\n {\n 'b-timeline--pending': hasPending.value,\n 'b-timeline--reverse': reverse,\n },\n]);\n\n// ─────────────────────────────────────────────\n// Item position helper\n// ─────────────────────────────────────────────\nfunction itemPositionClass(index: number, placement?: BTimelineItemPlacement): string {\n // Per-item placement overrides the global mode\n if (placement) {\n return placement === 'end' ? 'b-timeline-item--right' : 'b-timeline-item--left';\n }\n if (mode === 'alternate') {\n return index % 2 === 0 ? 'b-timeline-item--left' : 'b-timeline-item--right';\n }\n return mode === 'end' ? 'b-timeline-item--right' : 'b-timeline-item--left';\n}\n</script>\n\n<template>\n <ol :class=\"rootClasses\" aria-label=\"Timeline\">\n <!-- ── Data-driven items ── -->\n <template v-if=\"items && items.length\">\n <li\n v-for=\"(item, i) in orderedItems\"\n :key=\"i\"\n class=\"b-timeline-item\"\n :class=\"[\n dotColorClass(item.color),\n itemPositionClass(i, item.placement),\n { 'b-timeline-item--pending': item.loading },\n item.className,\n ]\"\n :style=\"[\n dotColorStyle(item.color),\n typeof item.style === 'string' ? item.style : item.style,\n ]\"\n >\n <!-- Label / title (opposing side) - always rendered as structural spacer; CSS hides in start mode -->\n <span class=\"b-timeline-item__label\">{{ item.title ?? '' }}</span>\n\n <!-- Line + dot -->\n <div class=\"b-timeline-item__tail\" aria-hidden=\"true\" />\n <div class=\"b-timeline-item__dot-wrapper\" aria-hidden=\"true\">\n <template v-if=\"item.icon\">\n <span class=\"b-timeline-item__dot--custom\" :data-icon=\"item.icon\" aria-hidden=\"true\" />\n </template>\n <template v-else-if=\"item.loading\">\n <span class=\"b-timeline-item__dot--pending-spinner\" />\n </template>\n <template v-else>\n <span class=\"b-timeline-item__dot\" />\n </template>\n </div>\n\n <!-- Content -->\n <div class=\"b-timeline-item__content\">{{ item.content }}</div>\n </li>\n </template>\n\n <!-- ── Slot-based items (default slot children) ── -->\n <template v-else>\n <slot />\n </template>\n\n <!-- ── Pending ghost item ── -->\n <li\n v-if=\"hasPending\"\n class=\"b-timeline-item b-timeline-item--pending\"\n :class=\"[itemPositionClass(items ? orderedItems.length : 0)]\"\n aria-label=\"Pending\"\n >\n <!-- Label spacer (structural; hidden in start mode via CSS) -->\n <span class=\"b-timeline-item__label\" />\n <div class=\"b-timeline-item__tail\" aria-hidden=\"true\" />\n <div class=\"b-timeline-item__dot-wrapper\" aria-hidden=\"true\">\n <slot name=\"pendingDot\">\n <span\n v-if=\"pendingDot\"\n class=\"b-timeline-item__dot--custom\"\n :data-icon=\"pendingDot\"\n aria-hidden=\"true\"\n />\n <span v-else class=\"b-timeline-item__dot--pending-spinner\" aria-hidden=\"true\" />\n </slot>\n </div>\n <div class=\"b-timeline-item__content\">{{ pendingContent }}</div>\n </li>\n </ol>\n</template>\n\n<style>\n/* ─────────────────────────────────────────────\n BTimeline - CSS custom properties (scoped to root)\n ───────────────────────────────────────────── */\n.b-timeline {\n /* ── Structural ── */\n --b-timeline-line-width: 2px;\n --b-timeline-line-color: oklch(90% 0.005 260);\n --b-timeline-item-padding-bottom: 20px;\n\n /* ── Dot ── */\n --b-timeline-dot-size: 10px;\n --b-timeline-dot-offset: 0px; /* fine-tune vertical alignment */\n --b-timeline-dot-border-width: 2px;\n --b-timeline-custom-dot-font-size: 20px; /* emoji / text custom dots */\n\n /* ── Blue (default) ── */\n --b-timeline-color-blue: oklch(54.6% 0.245 262.881);\n /* ── Green ── */\n --b-timeline-color-green: oklch(52% 0.17 145);\n /* ── Red ── */\n --b-timeline-color-red: oklch(50% 0.2 20);\n /* ── Gray ── */\n --b-timeline-color-gray: oklch(68% 0.01 260);\n\n /* ── Content text ── */\n --b-timeline-content-color: oklch(32% 0.02 260);\n --b-timeline-content-font-size: 14px;\n\n /* ── Label text ── */\n --b-timeline-label-color: oklch(52% 0.01 260);\n --b-timeline-label-font-size: 14px;\n\n /* ── Pending ── */\n --b-timeline-pending-line-style: dashed;\n --b-timeline-pending-dot-color: oklch(70% 0.01 260);\n\n /* ── Spinner ── */\n --b-timeline-spinner-size: 14px;\n --b-timeline-spinner-border-color: oklch(54.6% 0.245 262.881 / 20%);\n --b-timeline-spinner-accent-color: oklch(54.6% 0.245 262.881);\n --b-timeline-spinner-duration: 700ms;\n\n /* ── Transition ── */\n --b-timeline-transition-duration: 200ms;\n\n /* ── Layout ── */\n box-sizing: border-box;\n margin: 0;\n padding: 0;\n list-style: none;\n font-size: var(--b-timeline-content-font-size);\n line-height: 1.5;\n color: var(--b-timeline-content-color);\n}\n\n/* ─────────────────────────────────────────────\n Item\n ───────────────────────────────────────────── */\n.b-timeline-item {\n position: relative;\n display: flex;\n align-items: flex-start;\n padding-bottom: var(--b-timeline-item-padding-bottom);\n margin: 0;\n list-style: none;\n}\n\n/* last item - hide tail, collapse bottom padding */\n.b-timeline-item:last-child {\n padding-bottom: 0;\n}\n\n.b-timeline-item:last-child .b-timeline-item__tail {\n display: none;\n}\n\n/* ── Tail (vertical line) ── */\n.b-timeline-item__tail {\n position: absolute;\n top: calc(var(--b-timeline-dot-size) + 4px);\n left: calc(\n (var(--b-timeline-dot-size) / 2) - (var(--b-timeline-line-width) / 2)\n ); /* overridden per-mode */\n height: calc(100% - var(--b-timeline-dot-size) - 4px);\n width: var(--b-timeline-line-width);\n background: var(--b-timeline-line-color);\n transition: background var(--b-timeline-transition-duration);\n}\n\n/* ── Dot wrapper ── */\n.b-timeline-item__dot-wrapper {\n position: relative;\n flex-shrink: 0;\n width: var(--b-timeline-dot-size);\n height: var(--b-timeline-dot-size);\n margin-top: var(--b-timeline-dot-offset);\n z-index: 1;\n overflow: visible;\n}\n\n/* ── Standard dot ── */\n.b-timeline-item__dot {\n display: block;\n width: 100%;\n height: 100%;\n border-radius: 50%;\n background: var(--b-timeline-item-current-color, var(--b-timeline-color-blue));\n box-sizing: border-box;\n}\n\n/* ── Custom dot (icon / text) ── */\n.b-timeline-item__dot--custom {\n background: transparent;\n display: flex;\n align-items: center;\n justify-content: center;\n font-size: var(--b-timeline-custom-dot-font-size);\n line-height: 1;\n width: var(--b-timeline-custom-dot-font-size);\n height: var(--b-timeline-custom-dot-font-size);\n /* shift left/up so the icon stays centred over the dot position */\n position: absolute;\n top: 50%;\n left: 50%;\n transform: translate(-50%, -50%);\n color: var(--b-timeline-item-current-color, var(--b-timeline-color-blue));\n}\n\n/* Symbol rendered via ::before so no text node exists - avoids axe non-text-char rule */\n.b-timeline-item__dot--custom::before {\n content: attr(data-icon);\n}\n\n/* ─────────────────────────────────────────────\n Preset colors - set --b-timeline-item-current-color\n ───────────────────────────────────────────── */\n.b-timeline-item--blue {\n --b-timeline-item-current-color: var(--b-timeline-color-blue);\n}\n\n.b-timeline-item--green {\n --b-timeline-item-current-color: var(--b-timeline-color-green);\n}\n\n.b-timeline-item--red {\n --b-timeline-item-current-color: var(--b-timeline-color-red);\n}\n\n.b-timeline-item--gray {\n --b-timeline-item-current-color: var(--b-timeline-color-gray);\n}\n\n/* Custom (non-preset) color: provided via inline var */\n.b-timeline-item--custom {\n --b-timeline-item-current-color: var(--b-timeline-item-dot-color);\n}\n\n/* ─────────────────────────────────────────────\n Content & Label\n ───────────────────────────────────────────── */\n.b-timeline-item__content {\n flex: 1;\n padding-left: 12px;\n color: var(--b-timeline-content-color);\n font-size: var(--b-timeline-content-font-size);\n word-break: break-word;\n}\n\n.b-timeline-item__label {\n display: none; /* hidden in start mode; shown in alternate/end */\n color: var(--b-timeline-label-color);\n font-size: var(--b-timeline-label-font-size);\n text-align: right;\n flex-shrink: 0;\n}\n\n/* ─────────────────────────────────────────────\n Mode: start (default) - content right of line\n Each item: [dot] [content]\n ───────────────────────────────────────────── */\n.b-timeline--start .b-timeline-item {\n flex-direction: row;\n}\n\n.b-timeline--start .b-timeline-item__tail {\n left: calc((var(--b-timeline-dot-size) / 2) - (var(--b-timeline-line-width) / 2));\n}\n\n.b-timeline--start .b-timeline-item__label {\n display: none;\n}\n\n/* ─────────────────────────────────────────────\n Mode: end - content left of line\n Each item: [content] [dot]\n ───────────────────────────────────────────── */\n.b-timeline--end .b-timeline-item {\n flex-direction: row-reverse;\n}\n\n.b-timeline--end .b-timeline-item__content {\n padding-left: 0;\n padding-right: 12px;\n text-align: right;\n}\n\n.b-timeline--end .b-timeline-item__tail {\n right: calc((var(--b-timeline-dot-size) / 2) - (var(--b-timeline-line-width) / 2));\n left: auto;\n}\n\n.b-timeline--end .b-timeline-item__label {\n display: none;\n}\n\n/* ─────────────────────────────────────────────\n Mode: alternate\n Each row is always: [left-half][dot][right-half]\n Left items (even): left-half = label (right-aligned)\n right-half = content (left-aligned)\n Right items (odd): left-half = content (right-aligned)\n right-half = label (left-aligned)\n We use CSS `order` to swap - never flex-direction:row-reverse,\n which would flip the padding direction and break the gap.\n ───────────────────────────────────────────── */\n\n/* Label: always rendered as a structural spacer; hidden in start mode */\n.b-timeline--alternate .b-timeline-item__label {\n display: block;\n /* Each half = 50% of the row minus half the dot width.\n box-sizing:border-box means padding is included in this width,\n so the dot centre lands exactly at 50% of the row. */\n flex: 0 0 calc(50% - var(--b-timeline-dot-size) / 2);\n box-sizing: border-box;\n font-size: var(--b-timeline-label-font-size);\n color: var(--b-timeline-label-color);\n word-break: break-word;\n}\n\n/* Content: same symmetric half-width */\n.b-timeline--alternate .b-timeline-item__content {\n flex: 0 0 calc(50% - var(--b-timeline-dot-size) / 2);\n box-sizing: border-box;\n}\n\n/* Tail: always at exactly 50% of the row, regardless of which items have labels */\n.b-timeline--alternate .b-timeline-item__tail {\n left: calc(50% - var(--b-timeline-line-width) / 2);\n transform: none;\n}\n\n/* ── Left items (even): label LEFT → dot → content RIGHT ── */\n/* DOM order: label(1) tail(abs) dot(2) content(3) - already correct, no reordering needed */\n.b-timeline--alternate .b-timeline-item--left .b-timeline-item__label {\n order: 1;\n text-align: right;\n padding-right: 12px;\n padding-left: 0;\n}\n\n.b-timeline--alternate .b-timeline-item--left .b-timeline-item__dot-wrapper {\n order: 2;\n}\n\n.b-timeline--alternate .b-timeline-item--left .b-timeline-item__content {\n order: 3;\n text-align: left;\n padding-left: 12px;\n padding-right: 0;\n}\n\n/* ── Right items (odd): content LEFT → dot → label RIGHT ── */\n/* Use `order` to pull content before dot, push label after dot */\n.b-timeline--alternate .b-timeline-item--right .b-timeline-item__content {\n order: 1;\n text-align: right;\n padding-right: 12px;\n padding-left: 0;\n}\n\n.b-timeline--alternate .b-timeline-item--right .b-timeline-item__dot-wrapper {\n order: 2;\n}\n\n.b-timeline--alternate .b-timeline-item--right .b-timeline-item__label {\n order: 3;\n text-align: left;\n padding-left: 12px;\n padding-right: 0;\n}\n\n/* ─────────────────────────────────────────────\n Variant: outlined - hollow ring dot\n ───────────────────────────────────────────── */\n.b-timeline--outlined .b-timeline-item__dot {\n background: transparent;\n border: var(--b-timeline-dot-border-width) solid\n var(--b-timeline-item-current-color, var(--b-timeline-color-blue));\n}\n\n/* ─────────────────────────────────────────────\n Orientation: horizontal\n Items laid out left-to-right; tail becomes a\n horizontal bar running to the right.\n ───────────────────────────────────────────── */\n.b-timeline--horizontal {\n display: flex;\n flex-direction: row;\n align-items: flex-start;\n overflow-x: auto;\n}\n\n.b-timeline--horizontal.b-timeline--start .b-timeline-item,\n.b-timeline--horizontal.b-timeline--end .b-timeline-item {\n flex-direction: column;\n align-items: center;\n flex: 1;\n padding-bottom: 0;\n padding-right: 0;\n min-width: 80px;\n}\n\n/* Horizontal tail: runs right from the dot */\n.b-timeline--horizontal .b-timeline-item__tail {\n top: calc(var(--b-timeline-dot-size) / 2 - var(--b-timeline-line-width) / 2);\n left: calc(var(--b-timeline-dot-size) + 4px);\n width: calc(100% - var(--b-timeline-dot-size) - 4px);\n height: var(--b-timeline-line-width);\n right: auto;\n bottom: auto;\n}\n\n/* In horizontal mode the last item still hides its tail */\n.b-timeline--horizontal .b-timeline-item:last-child .b-timeline-item__tail {\n display: none;\n}\n\n/* Dot: centred horizontally above content */\n.b-timeline--horizontal .b-timeline-item__dot-wrapper {\n margin-top: 0;\n flex-shrink: 0;\n}\n\n/* Content sits below the dot row */\n.b-timeline--horizontal .b-timeline-item__content {\n padding-left: 0;\n padding-top: 8px;\n text-align: center;\n width: 100%;\n}\n\n/* Label sits above the dot row (for start mode) */\n.b-timeline--horizontal.b-timeline--start .b-timeline-item__label {\n display: block;\n text-align: center;\n padding-bottom: 8px;\n order: 1;\n}\n\n.b-timeline--horizontal.b-timeline--start .b-timeline-item__dot-wrapper {\n order: 2;\n}\n\n.b-timeline--horizontal.b-timeline--start .b-timeline-item__content {\n order: 3;\n}\n\n/* For end mode, label goes below content */\n.b-timeline--horizontal.b-timeline--end .b-timeline-item__content {\n order: 1;\n padding-top: 8px;\n padding-right: 0;\n text-align: center;\n}\n\n.b-timeline--horizontal.b-timeline--end .b-timeline-item__dot-wrapper {\n order: 2;\n}\n\n.b-timeline--horizontal.b-timeline--end .b-timeline-item__label {\n display: block;\n text-align: center;\n padding-top: 8px;\n order: 3;\n}\n\n/* ─────────────────────────────────────────────\n Pending item\n ───────────────────────────────────────────── */\n.b-timeline-item--pending .b-timeline-item__tail {\n border-left: var(--b-timeline-line-width) var(--b-timeline-pending-line-style)\n var(--b-timeline-line-color);\n background: transparent;\n}\n\n.b-timeline--start .b-timeline-item--pending .b-timeline-item__tail {\n /* override the absolute left, matches .b-timeline--start logic */\n left: calc((var(--b-timeline-dot-size) / 2) - (var(--b-timeline-line-width) / 2));\n}\n\n/* Horizontal pending tail */\n.b-timeline--horizontal .b-timeline-item--pending .b-timeline-item__tail {\n border-left: none;\n border-top: var(--b-timeline-line-width) var(--b-timeline-pending-line-style)\n var(--b-timeline-line-color);\n background: transparent;\n height: 0;\n}\n\n/* ── Default pending spinner ── */\n.b-timeline-item__dot--pending-spinner {\n display: block;\n width: var(--b-timeline-spinner-size);\n height: var(--b-timeline-spinner-size);\n margin-left: calc((var(--b-timeline-dot-size) - var(--b-timeline-spinner-size)) / 2);\n border-radius: 50%;\n border: var(--b-timeline-dot-border-width) solid var(--b-timeline-spinner-border-color);\n border-top-color: var(--b-timeline-spinner-accent-color);\n animation: b-timeline-spin var(--b-timeline-spinner-duration) linear infinite;\n}\n\n@keyframes b-timeline-spin {\n to {\n transform: rotate(360deg);\n }\n}\n\n/* ─────────────────────────────────────────────\n Dark mode\n ───────────────────────────────────────────── */\n[data-prefers-color='dark'] .b-timeline {\n --b-timeline-line-color: oklch(32% 0.012 260);\n --b-timeline-content-color: oklch(82% 0.01 260);\n --b-timeline-label-color: oklch(60% 0.01 260);\n --b-timeline-color-gray: oklch(50% 0.01 260);\n --b-timeline-spinner-border-color: oklch(54.6% 0.245 262.881 / 15%);\n}\n\n@media (prefers-color-scheme: dark) {\n [data-prefers-color='system'] .b-timeline {\n --b-timeline-line-color: oklch(32% 0.012 260);\n --b-timeline-content-color: oklch(82% 0.01 260);\n --b-timeline-label-color: oklch(60% 0.01 260);\n --b-timeline-color-gray: oklch(50% 0.01 260);\n --b-timeline-spinner-border-color: oklch(54.6% 0.245 262.881 / 15%);\n }\n}\n\n/* ─────────────────────────────────────────────\n Reduced motion\n ───────────────────────────────────────────── */\n@media (prefers-reduced-motion: reduce) {\n .b-timeline {\n --b-timeline-transition-duration: 0ms;\n --b-timeline-spinner-duration: 0ms;\n }\n\n .b-timeline-item__dot--pending-spinner {\n animation: none;\n border-top-color: var(--b-timeline-spinner-border-color);\n opacity: 0.6;\n }\n}\n</style>\n"],"mappings":""}
1
+ {"version":3,"file":"design-system207.js","names":[],"sources":["../src/components/BSteps/BSteps.vue?vue&type=script&setup=true&lang.ts"],"sourcesContent":["import { useModel as _useModel, mergeModels as _mergeModels, defineComponent as _defineComponent } from 'vue'\nimport { unref as _unref, renderList as _renderList, Fragment as _Fragment, openBlock as _openBlock, createElementBlock as _createElementBlock, createBlock as _createBlock, createCommentVNode as _createCommentVNode, toDisplayString as _toDisplayString, normalizeClass as _normalizeClass, createElementVNode as _createElementVNode, normalizeStyle as _normalizeStyle } from \"vue\"\n\nconst _hoisted_1 = [\"data-status\"]\nconst _hoisted_2 = [\"role\", \"tabindex\", \"aria-disabled\", \"aria-current\", \"onClick\", \"onKeydown\"]\nconst _hoisted_3 = { class: \"b:flex b:items-center b:gap-x-2\" }\nconst _hoisted_4 = {\n key: 0,\n \"aria-hidden\": \"true\",\n class: \"b-steps__tail\"\n}\n\nimport BIcon from '@/components/BIcon/BIcon.vue';\nimport {\n BCommonSize,\n BIconSize,\n BStepsDirection,\n BStepsLabelPlacement,\n BStepsStatus,\n BStepsType,\n type BStepItem,\n} from '@/types.ts';\nimport { computed, toRefs } from 'vue';\n\nexport interface BStepsProps {\n /**\n * The step items to render.\n */\n items?: BStepItem[];\n /**\n * Status applied to the current step if not overridden by the item.\n */\n status?: `${BStepsStatus}`;\n /**\n * Layout direction.\n */\n direction?: `${BStepsDirection}`;\n /**\n * Size of the step icons and text.\n */\n size?: `${BCommonSize}`;\n /**\n * Placement of labels for horizontal steps.\n */\n labelPlacement?: `${BStepsLabelPlacement}`;\n /**\n * Step type styling.\n */\n type?: `${BStepsType}`;\n}\n\n\nexport default /*@__PURE__*/_defineComponent({\n __name: 'BSteps',\n props: /*@__PURE__*/_mergeModels({\n items: { default: () => [] },\n status: { default: BStepsStatus.Process },\n direction: { default: BStepsDirection.Horizontal },\n size: { default: BCommonSize.Medium },\n labelPlacement: { default: BStepsLabelPlacement.Horizontal },\n type: { default: BStepsType.Default }\n }, {\n \"modelValue\": { default: 0 },\n \"modelModifiers\": {},\n }),\n emits: /*@__PURE__*/_mergeModels([\"change\"], [\"update:modelValue\"]),\n setup(__props: any, { emit: __emit }) {\n\nconst props = __props;\nconst { items, status, direction, size, labelPlacement, type } = toRefs(props);\nconst model = _useModel<number>(__props, \"modelValue\");\n\nconst emit = __emit;\n\nconst normalizedSize = computed(() =>\n size.value === BCommonSize.Small ? BCommonSize.Small : BCommonSize.Medium,\n);\nconst iconSize = computed(() =>\n normalizedSize.value === BCommonSize.Small ? BIconSize.Small : BIconSize.Medium,\n);\n\nconst rootStyle = computed(() => ({\n '--b-steps-icon-size': normalizedSize.value === BCommonSize.Small ? '1.5rem' : '2rem',\n '--b-steps-gap': normalizedSize.value === BCommonSize.Small ? '0.5rem' : '0.75rem',\n}));\n\nconst titleSizeClass = computed(() =>\n normalizedSize.value === BCommonSize.Small ? 'b:text-sm' : 'b:text-base',\n);\nconst descriptionSizeClass = computed(() =>\n normalizedSize.value === BCommonSize.Small ? 'b:text-xs' : 'b:text-sm',\n);\n\nconst isClickable = computed(() => type.value === BStepsType.Navigation);\n\nconst getStepStatus = (item: BStepItem, index: number) => {\n if (item.status) {\n return item.status;\n }\n if (index === model.value) {\n return status.value || BStepsStatus.Process;\n }\n if (index < model.value) {\n return BStepsStatus.Finish;\n }\n return BStepsStatus.Wait;\n};\n\nconst getTailColor = (status: `${BStepsStatus}`) => {\n switch (status) {\n case BStepsStatus.Finish:\n case BStepsStatus.Process:\n return 'var(--b-color-primary)';\n case BStepsStatus.Error:\n return 'var(--b-color-failure)';\n case BStepsStatus.Wait:\n default:\n return 'var(--b-color-zinc-200)';\n }\n};\n\nconst onStepClick = (item: BStepItem, index: number) => {\n if (!isClickable.value || item.disabled) {\n return;\n }\n model.value = index;\n emit('change', index);\n};\n\nconst onStepKeydown = (event: KeyboardEvent, item: BStepItem, index: number) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onStepClick(item, index);\n }\n};\n\nconst iconClass = (status: `${BStepsStatus}`) => ({\n 'b:border-secondary b:bg-white b:text-secondary': status === BStepsStatus.Wait,\n 'b:border-primary b:bg-primary b:text-white': status === BStepsStatus.Process,\n 'b:border-primary b:bg-white b:text-primary': status === BStepsStatus.Finish,\n 'b:border-failure b:bg-white b:text-failure': status === BStepsStatus.Error,\n});\nconst titleClass = (status: `${BStepsStatus}`) => ({\n 'b:text-black-base': status === BStepsStatus.Process || status === BStepsStatus.Finish,\n 'b:text-failure': status === BStepsStatus.Error,\n 'b:text-black/65': status === BStepsStatus.Wait,\n});\nconst descriptionClass = (status: `${BStepsStatus}`) => ({\n 'b:text-black/65': status !== BStepsStatus.Error,\n 'b:text-failure': status === BStepsStatus.Error,\n});\n\nreturn (_ctx: any,_cache: any) => {\n return (_openBlock(), _createElementBlock(\"ol\", {\n class: _normalizeClass([\"b-steps\", [\n {\n 'b-steps--horizontal': _unref(direction) === _unref(BStepsDirection).Horizontal,\n 'b-steps--vertical': _unref(direction) === _unref(BStepsDirection).Vertical,\n 'b-steps--label-vertical':\n _unref(direction) === _unref(BStepsDirection).Horizontal &&\n _unref(labelPlacement) === _unref(BStepsLabelPlacement).Vertical,\n 'b-steps--navigation': _unref(type) === _unref(BStepsType).Navigation,\n 'b-steps--inline': _unref(type) === _unref(BStepsType).Inline,\n },\n ]]),\n style: _normalizeStyle(rootStyle.value)\n }, [\n (_openBlock(true), _createElementBlock(_Fragment, null, _renderList(_unref(items), (item, index) => {\n return (_openBlock(), _createElementBlock(\"li\", {\n key: `${item.title}-${index}`,\n class: _normalizeClass([\"b-steps__item\", [\n { 'b:opacity-50': item.disabled },\n { 'b-steps__item--clickable': isClickable.value && !item.disabled },\n ]]),\n \"data-status\": getStepStatus(item, index),\n style: _normalizeStyle({ '--b-steps-tail-color': getTailColor(getStepStatus(item, index)) })\n }, [\n _createElementVNode(\"div\", {\n class: \"b-steps__item-inner\",\n role: isClickable.value && !item.disabled ? 'button' : undefined,\n tabindex: isClickable.value && !item.disabled ? 0 : undefined,\n \"aria-disabled\": item.disabled ? 'true' : undefined,\n \"aria-current\": index === model.value ? 'step' : undefined,\n onClick: ($event: any) => (onStepClick(item, index)),\n onKeydown: ($event: any) => (onStepKeydown($event, item, index))\n }, [\n _createElementVNode(\"div\", {\n class: _normalizeClass([\"b-steps__icon b:flex b:items-center b:justify-center b:rounded-full b:border\", [\n iconClass(getStepStatus(item, index)),\n {\n 'b:h-6 b:w-6': normalizedSize.value === _unref(BCommonSize).Small,\n 'b:h-8 b:w-8': normalizedSize.value === _unref(BCommonSize).Medium,\n },\n ]])\n }, [\n (item.icon)\n ? (_openBlock(), _createBlock(BIcon, {\n key: 0,\n icon: item.icon,\n size: iconSize.value\n }, null, 8, [\"icon\", \"size\"]))\n : (getStepStatus(item, index) === _unref(BStepsStatus).Finish)\n ? (_openBlock(), _createBlock(BIcon, {\n key: 1,\n icon: \"check\",\n size: iconSize.value\n }, null, 8, [\"size\"]))\n : (getStepStatus(item, index) === _unref(BStepsStatus).Error)\n ? (_openBlock(), _createBlock(BIcon, {\n key: 2,\n icon: \"xmark\",\n size: iconSize.value\n }, null, 8, [\"size\"]))\n : (_openBlock(), _createElementBlock(\"span\", {\n key: 3,\n class: _normalizeClass(titleSizeClass.value)\n }, _toDisplayString(index + 1), 3))\n ], 2),\n _createElementVNode(\"div\", {\n class: _normalizeClass([\"b-steps__content b:flex b:flex-col b:gap-y-1\", [\n {\n 'b:items-center b:text-center':\n _unref(direction) === _unref(BStepsDirection).Horizontal &&\n _unref(labelPlacement) === _unref(BStepsLabelPlacement).Vertical,\n },\n ]])\n }, [\n _createElementVNode(\"div\", _hoisted_3, [\n _createElementVNode(\"span\", {\n class: _normalizeClass([\"b:font-medium\", [titleSizeClass.value, titleClass(getStepStatus(item, index))]])\n }, _toDisplayString(item.title), 3),\n (item.subTitle)\n ? (_openBlock(), _createElementBlock(\"span\", {\n key: 0,\n class: _normalizeClass([\"b:text-xs b:text-black/65\", titleClass(getStepStatus(item, index))])\n }, _toDisplayString(item.subTitle), 3))\n : _createCommentVNode(\"\", true)\n ]),\n (item.description)\n ? (_openBlock(), _createElementBlock(\"p\", {\n key: 0,\n class: _normalizeClass([\"b:leading-snug\", [descriptionSizeClass.value, descriptionClass(getStepStatus(item, index))]])\n }, _toDisplayString(item.description), 3))\n : _createCommentVNode(\"\", true)\n ], 2)\n ], 40, _hoisted_2),\n (_unref(direction) === _unref(BStepsDirection).Horizontal && index < _unref(items).length - 1)\n ? (_openBlock(), _createElementBlock(\"span\", _hoisted_4))\n : _createCommentVNode(\"\", true)\n ], 14, _hoisted_1))\n }), 128))\n ], 6))\n}\n}\n\n})"],"mappings":"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"}
@@ -1,7 +1,9 @@
1
- import e from "./design-system208.js";
2
- //#region src/components/BTimeline/BTimelineItem.vue
3
- var t = e;
1
+ import e from "./design-system14.js";
2
+ import t from "./design-system207.js";
3
+ /* empty css */
4
+ //#region src/components/BSteps/BSteps.vue
5
+ var n = /* @__PURE__ */ e(t, [["__scopeId", "data-v-75d0dd09"]]);
4
6
  //#endregion
5
- export { t as default };
7
+ export { n as default };
6
8
 
7
9
  //# sourceMappingURL=design-system209.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"design-system209.js","names":[],"sources":["../src/components/BTimeline/BTimelineItem.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport { computed, inject } from 'vue';\n\nimport type { BTimelineItemColor, BTimelineItemPlacement, BTimelineVariant } from './types';\n\n// ─────────────────────────────────────────────\n// Props\n// ─────────────────────────────────────────────\nconst {\n color = 'blue',\n icon,\n loading = false,\n placement,\n} = defineProps<{\n /**\n * Dot color - preset (`blue` | `red` | `green` | `gray`) or any CSS color.\n * @default 'blue'\n */\n color?: BTimelineItemColor;\n /**\n * Custom dot content string/emoji. Use the `#icon` slot for rich content.\n */\n icon?: string;\n /**\n * Shows a spinner on this item's dot - use for in-progress items.\n * @default false\n */\n loading?: boolean;\n /**\n * Override the parent timeline's mode for this item only.\n * Pins the item to the `'start'` or `'end'` side regardless of mode.\n */\n placement?: BTimelineItemPlacement;\n}>();\n\n// ─────────────────────────────────────────────\n// Slots\n// ─────────────────────────────────────────────\ndefineSlots<{\n /** Main content of the timeline item. */\n default?(): unknown;\n /** Custom dot/icon content - fully replaces the standard circle. */\n icon?(): unknown;\n /** Label shown on the opposing side in alternate/end mode. */\n label?(): unknown;\n}>();\n\n// ─────────────────────────────────────────────\n// Context from parent (mode + item index + variant)\n// ─────────────────────────────────────────────\nconst timelineMode = inject<'start' | 'alternate' | 'end'>('b-timeline-mode', 'start');\nconst timelineIndex = inject<number>('b-timeline-item-index', 0);\nconst timelineVariant = inject<BTimelineVariant>('b-timeline-variant', 'filled');\n\n// ─────────────────────────────────────────────\n// Color helpers\n// ─────────────────────────────────────────────\nconst PRESET_COLORS: string[] = ['blue', 'red', 'green', 'gray'];\n\nconst isPreset = computed(() => PRESET_COLORS.includes(color));\n\nconst colorClass = computed(() =>\n isPreset.value ? `b-timeline-item--${color}` : 'b-timeline-item--custom',\n);\n\nconst colorStyle = computed<Record<string, string> | undefined>(() =>\n !isPreset.value ? { '--b-timeline-item-dot-color': color } : undefined,\n);\n\n// ─────────────────────────────────────────────\n// Position class\n// ─────────────────────────────────────────────\nconst positionClass = computed(() => {\n // Per-item placement overrides the global mode\n if (placement) {\n return placement === 'end' ? 'b-timeline-item--right' : 'b-timeline-item--left';\n }\n if (timelineMode === 'alternate') {\n return timelineIndex % 2 === 0 ? 'b-timeline-item--left' : 'b-timeline-item--right';\n }\n return timelineMode === 'end' ? 'b-timeline-item--right' : 'b-timeline-item--left';\n});\n\n// ─────────────────────────────────────────────\n// Root classes\n// ─────────────────────────────────────────────\nconst rootClasses = computed(() => [\n 'b-timeline-item',\n colorClass.value,\n positionClass.value,\n { 'b-timeline-item--pending': loading },\n]);\n\n// ─────────────────────────────────────────────\n// Variant (injected from parent BTimeline)\n// ─────────────────────────────────────────────\nconst variantClass = computed(() =>\n timelineVariant === 'outlined' ? 'b-timeline-item__dot--outlined' : undefined,\n);\n</script>\n\n<template>\n <li :class=\"rootClasses\" :style=\"colorStyle\">\n <!-- Label - always rendered as a structural spacer; CSS hides it in start mode -->\n <span class=\"b-timeline-item__label\">\n <slot name=\"label\" />\n </span>\n\n <!-- Tail (connecting line) -->\n <div class=\"b-timeline-item__tail\" aria-hidden=\"true\" />\n\n <!-- Dot -->\n <div class=\"b-timeline-item__dot-wrapper\" aria-hidden=\"true\">\n <slot name=\"icon\">\n <template v-if=\"icon\">\n <span\n class=\"b-timeline-item__dot b-timeline-item__dot--custom\"\n :data-icon=\"icon\"\n aria-hidden=\"true\"\n />\n </template>\n <template v-else-if=\"loading\">\n <span class=\"b-timeline-item__dot--pending-spinner\" />\n </template>\n <template v-else>\n <span class=\"b-timeline-item__dot\" :class=\"variantClass\" />\n </template>\n </slot>\n </div>\n\n <!-- Content -->\n <div class=\"b-timeline-item__content\">\n <slot />\n </div>\n </li>\n</template>\n"],"mappings":""}
1
+ {"version":3,"file":"design-system209.js","names":[],"sources":["../src/components/BSteps/BSteps.vue"],"sourcesContent":["<script setup lang=\"ts\">\nimport BIcon from '@/components/BIcon/BIcon.vue';\nimport {\n BCommonSize,\n BIconSize,\n BStepsDirection,\n BStepsLabelPlacement,\n BStepsStatus,\n BStepsType,\n type BStepItem,\n} from '@/types.ts';\nimport { computed, toRefs } from 'vue';\n\nexport interface BStepsProps {\n /**\n * The step items to render.\n */\n items?: BStepItem[];\n /**\n * Status applied to the current step if not overridden by the item.\n */\n status?: `${BStepsStatus}`;\n /**\n * Layout direction.\n */\n direction?: `${BStepsDirection}`;\n /**\n * Size of the step icons and text.\n */\n size?: `${BCommonSize}`;\n /**\n * Placement of labels for horizontal steps.\n */\n labelPlacement?: `${BStepsLabelPlacement}`;\n /**\n * Step type styling.\n */\n type?: `${BStepsType}`;\n}\n\nconst props = withDefaults(defineProps<BStepsProps>(), {\n items: () => [],\n status: BStepsStatus.Process,\n direction: BStepsDirection.Horizontal,\n size: BCommonSize.Medium,\n labelPlacement: BStepsLabelPlacement.Horizontal,\n type: BStepsType.Default,\n});\nconst { items, status, direction, size, labelPlacement, type } = toRefs(props);\nconst model = defineModel<number>({ default: 0 });\n\nconst emit = defineEmits<{\n /**\n * Emitted when the current step changes via user interaction.\n */\n change: [value: number];\n}>();\n\nconst normalizedSize = computed(() =>\n size.value === BCommonSize.Small ? BCommonSize.Small : BCommonSize.Medium,\n);\nconst iconSize = computed(() =>\n normalizedSize.value === BCommonSize.Small ? BIconSize.Small : BIconSize.Medium,\n);\n\nconst rootStyle = computed(() => ({\n '--b-steps-icon-size': normalizedSize.value === BCommonSize.Small ? '1.5rem' : '2rem',\n '--b-steps-gap': normalizedSize.value === BCommonSize.Small ? '0.5rem' : '0.75rem',\n}));\n\nconst titleSizeClass = computed(() =>\n normalizedSize.value === BCommonSize.Small ? 'b:text-sm' : 'b:text-base',\n);\nconst descriptionSizeClass = computed(() =>\n normalizedSize.value === BCommonSize.Small ? 'b:text-xs' : 'b:text-sm',\n);\n\nconst isClickable = computed(() => type.value === BStepsType.Navigation);\n\nconst getStepStatus = (item: BStepItem, index: number) => {\n if (item.status) {\n return item.status;\n }\n if (index === model.value) {\n return status.value || BStepsStatus.Process;\n }\n if (index < model.value) {\n return BStepsStatus.Finish;\n }\n return BStepsStatus.Wait;\n};\n\nconst getTailColor = (status: `${BStepsStatus}`) => {\n switch (status) {\n case BStepsStatus.Finish:\n case BStepsStatus.Process:\n return 'var(--b-color-primary)';\n case BStepsStatus.Error:\n return 'var(--b-color-failure)';\n case BStepsStatus.Wait:\n default:\n return 'var(--b-color-zinc-200)';\n }\n};\n\nconst onStepClick = (item: BStepItem, index: number) => {\n if (!isClickable.value || item.disabled) {\n return;\n }\n model.value = index;\n emit('change', index);\n};\n\nconst onStepKeydown = (event: KeyboardEvent, item: BStepItem, index: number) => {\n if (event.key === 'Enter' || event.key === ' ') {\n event.preventDefault();\n onStepClick(item, index);\n }\n};\n\nconst iconClass = (status: `${BStepsStatus}`) => ({\n 'b:border-secondary b:bg-white b:text-secondary': status === BStepsStatus.Wait,\n 'b:border-primary b:bg-primary b:text-white': status === BStepsStatus.Process,\n 'b:border-primary b:bg-white b:text-primary': status === BStepsStatus.Finish,\n 'b:border-failure b:bg-white b:text-failure': status === BStepsStatus.Error,\n});\nconst titleClass = (status: `${BStepsStatus}`) => ({\n 'b:text-black-base': status === BStepsStatus.Process || status === BStepsStatus.Finish,\n 'b:text-failure': status === BStepsStatus.Error,\n 'b:text-black/65': status === BStepsStatus.Wait,\n});\nconst descriptionClass = (status: `${BStepsStatus}`) => ({\n 'b:text-black/65': status !== BStepsStatus.Error,\n 'b:text-failure': status === BStepsStatus.Error,\n});\n</script>\n\n<template>\n <ol\n class=\"b-steps\"\n :class=\"[\n {\n 'b-steps--horizontal': direction === BStepsDirection.Horizontal,\n 'b-steps--vertical': direction === BStepsDirection.Vertical,\n 'b-steps--label-vertical':\n direction === BStepsDirection.Horizontal &&\n labelPlacement === BStepsLabelPlacement.Vertical,\n 'b-steps--navigation': type === BStepsType.Navigation,\n 'b-steps--inline': type === BStepsType.Inline,\n },\n ]\"\n :style=\"rootStyle\"\n >\n <li\n v-for=\"(item, index) in items\"\n :key=\"`${item.title}-${index}`\"\n class=\"b-steps__item\"\n :class=\"[\n { 'b:opacity-50': item.disabled },\n { 'b-steps__item--clickable': isClickable && !item.disabled },\n ]\"\n :data-status=\"getStepStatus(item, index)\"\n :style=\"{ '--b-steps-tail-color': getTailColor(getStepStatus(item, index)) }\"\n >\n <div\n class=\"b-steps__item-inner\"\n :role=\"isClickable && !item.disabled ? 'button' : undefined\"\n :tabindex=\"isClickable && !item.disabled ? 0 : undefined\"\n :aria-disabled=\"item.disabled ? 'true' : undefined\"\n :aria-current=\"index === model ? 'step' : undefined\"\n @click=\"onStepClick(item, index)\"\n @keydown=\"onStepKeydown($event, item, index)\"\n >\n <div\n class=\"b-steps__icon b:flex b:items-center b:justify-center b:rounded-full b:border\"\n :class=\"[\n iconClass(getStepStatus(item, index)),\n {\n 'b:h-6 b:w-6': normalizedSize === BCommonSize.Small,\n 'b:h-8 b:w-8': normalizedSize === BCommonSize.Medium,\n },\n ]\"\n >\n <template v-if=\"item.icon\">\n <BIcon :icon=\"item.icon\" :size=\"iconSize\" />\n </template>\n <template v-else-if=\"getStepStatus(item, index) === BStepsStatus.Finish\">\n <BIcon icon=\"check\" :size=\"iconSize\" />\n </template>\n <template v-else-if=\"getStepStatus(item, index) === BStepsStatus.Error\">\n <BIcon icon=\"xmark\" :size=\"iconSize\" />\n </template>\n <template v-else>\n <span :class=\"titleSizeClass\">{{ index + 1 }}</span>\n </template>\n </div>\n\n <div\n class=\"b-steps__content b:flex b:flex-col b:gap-y-1\"\n :class=\"[\n {\n 'b:items-center b:text-center':\n direction === BStepsDirection.Horizontal &&\n labelPlacement === BStepsLabelPlacement.Vertical,\n },\n ]\"\n >\n <div class=\"b:flex b:items-center b:gap-x-2\">\n <span\n class=\"b:font-medium\"\n :class=\"[titleSizeClass, titleClass(getStepStatus(item, index))]\"\n >\n {{ item.title }}\n </span>\n <span\n v-if=\"item.subTitle\"\n class=\"b:text-xs b:text-black/65\"\n :class=\"titleClass(getStepStatus(item, index))\"\n >\n {{ item.subTitle }}\n </span>\n </div>\n <p\n v-if=\"item.description\"\n class=\"b:leading-snug\"\n :class=\"[descriptionSizeClass, descriptionClass(getStepStatus(item, index))]\"\n >\n {{ item.description }}\n </p>\n </div>\n </div>\n <span\n v-if=\"direction === BStepsDirection.Horizontal && index < items.length - 1\"\n aria-hidden=\"true\"\n class=\"b-steps__tail\"\n />\n </li>\n </ol>\n</template>\n\n<style scoped>\n.b-steps {\n display: flex;\n gap: var(--b-steps-gap);\n}\n\n.b-steps--vertical {\n flex-direction: column;\n}\n\n.b-steps__item {\n position: relative;\n flex: 1;\n min-width: 0;\n}\n\n.b-steps__item-inner {\n display: flex;\n align-items: flex-start;\n gap: var(--b-steps-gap);\n flex: 0 1 auto;\n min-width: 0;\n}\n\n.b-steps__icon {\n flex-shrink: 0;\n}\n\n.b-steps__content {\n flex: 1 1 auto;\n min-width: 0;\n}\n\n.b-steps--label-vertical .b-steps__item-inner {\n flex-direction: column;\n align-items: center;\n}\n\n.b-steps--inline .b-steps__item-inner {\n align-items: center;\n}\n\n.b-steps--inline .b-steps__content {\n flex-direction: row;\n align-items: center;\n gap: var(--b-steps-gap);\n}\n\n.b-steps--inline .b-steps__content p {\n display: none;\n}\n\n.b-steps__item--clickable .b-steps__item-inner {\n cursor: pointer;\n}\n\n.b-steps--horizontal .b-steps__item {\n display: flex;\n align-items: flex-start;\n gap: var(--b-steps-gap);\n}\n\n.b-steps--vertical .b-steps__item {\n padding-bottom: var(--b-steps-gap);\n}\n\n.b-steps--vertical .b-steps__item::after {\n content: '';\n position: absolute;\n top: calc(var(--b-steps-icon-size) + var(--b-steps-gap));\n left: calc(var(--b-steps-icon-size) / 2);\n bottom: 0;\n width: 1px;\n background-color: var(--b-steps-tail-color);\n}\n\n.b-steps--vertical .b-steps__item:last-child::after {\n display: none;\n}\n\n.b-steps__tail {\n flex: 1 1 0;\n min-width: 1.5rem;\n height: 1px;\n margin-top: calc(var(--b-steps-icon-size) / 2);\n background-color: var(--b-steps-tail-color);\n}\n\n.b-steps--navigation .b-steps__item--clickable .b-steps__content {\n transition: color 0.2s ease;\n}\n\n.b-steps--navigation .b-steps__item--clickable:hover .b-steps__content {\n color: var(--b-color-primary);\n}\n</style>\n"],"mappings":""}