@keyfunc/keybricks-ds 1.0.3 → 2.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/DEPLOY.md +4 -4
- package/DESIGN.md +154 -53
- package/INTEGRATION.md +176 -36
- package/SKILL.md +6 -4
- package/_adherence.oxlintrc.json +183 -72
- package/_scripts/build-index.mjs +9 -0
- package/_scripts/build-tokens.mjs +5 -2
- package/assets/icons/icon-index.js +1 -1
- package/assets/icons/icon-index.json +1 -1
- package/components/_cards/accordion.card.html +2 -2
- package/components/_cards/action-chip.card.html +8 -3
- package/components/_cards/activity.card.html +2 -2
- package/components/_cards/alert.card.html +2 -2
- package/components/_cards/app-chrome.card.html +4 -4
- package/components/_cards/banner.card.html +1 -1
- package/components/_cards/breadcrumb.card.html +2 -2
- package/components/_cards/button-1-base.card.html +2 -2
- package/components/_cards/button-2-states.card.html +14 -14
- package/components/_cards/button-3-sizes-icons.card.html +1 -1
- package/components/_cards/button-4-group.card.html +5 -5
- package/components/_cards/canvas-zoom-controls.card.html +1 -1
- package/components/_cards/cards-indicators.card.html +2 -2
- package/components/_cards/charts-1-sparkline.card.html +2 -2
- package/components/_cards/charts-10-gauge.card.html +4 -4
- package/components/_cards/charts-11-funnel.card.html +2 -2
- package/components/_cards/charts-12-treemap.card.html +2 -2
- package/components/_cards/charts-14-radar.card.html +1 -1
- package/components/_cards/charts-15-distribution.card.html +1 -1
- package/components/_cards/charts-16-pareto.card.html +2 -2
- package/components/_cards/charts-17-candlestick.card.html +2 -2
- package/components/_cards/charts-18-sankey.card.html +2 -2
- package/components/_cards/charts-19-chord.card.html +2 -2
- package/components/_cards/charts-2-line.card.html +2 -2
- package/components/_cards/charts-20-sunburst.card.html +2 -2
- package/components/_cards/charts-21-worldmap.card.html +2 -2
- package/components/_cards/charts-22-gantt.card.html +2 -2
- package/components/_cards/charts-23-bar3d.card.html +2 -2
- package/components/_cards/charts-24-pie3d.card.html +2 -2
- package/components/_cards/charts-25-surface3d.card.html +2 -2
- package/components/_cards/charts-26-scatter3d.card.html +2 -2
- package/components/_cards/charts-27-ribbon3d.card.html +2 -2
- package/components/_cards/charts-3-bar.card.html +2 -2
- package/components/_cards/charts-4-barlist.card.html +2 -2
- package/components/_cards/charts-5-donut.card.html +3 -3
- package/components/_cards/charts-6-scatter.card.html +2 -2
- package/components/_cards/charts-7-heatmap.card.html +2 -2
- package/components/_cards/charts-8-waterfall.card.html +2 -2
- package/components/_cards/charts-9-bullet.card.html +2 -2
- package/components/_cards/charts-99-fullpage.card.html +5 -5
- package/components/_cards/checkbox.card.html +4 -4
- package/components/_cards/codeblock.card.html +1 -1
- package/components/_cards/combobox.card.html +3 -2
- package/components/_cards/context-menu.card.html +3 -2
- package/components/_cards/date-picker.card.html +5 -2
- package/components/_cards/diffvalue.card.html +2 -2
- package/components/_cards/divider.card.html +3 -3
- package/components/_cards/drawer.card.html +2 -2
- package/components/_cards/dropdown-menu.card.html +6 -6
- package/components/_cards/dropzone.card.html +1 -1
- package/components/_cards/empty-state.card.html +5 -5
- package/components/_cards/filter-bar.card.html +5 -5
- package/components/_cards/icon-button.card.html +2 -2
- package/components/_cards/icons-1-core.card.html +2 -2
- package/components/_cards/icons-2-feather.card.html +3 -3
- package/components/_cards/icons-3-unicons.card.html +3 -3
- package/components/_cards/input.card.html +5 -2
- package/components/_cards/kbd.card.html +2 -2
- package/components/_cards/keyvalue.card.html +2 -2
- package/components/_cards/listrow.card.html +2 -2
- package/components/_cards/loading.card.html +2 -2
- package/components/_cards/log-viewer.card.html +2 -2
- package/components/_cards/modal.card.html +9 -9
- package/components/_cards/multi-select.card.html +3 -2
- package/components/_cards/number-stepper.card.html +3 -2
- package/components/_cards/pagination.card.html +3 -2
- package/components/_cards/people.card.html +3 -3
- package/components/_cards/pipeline-node.card.html +2 -2
- package/components/_cards/pipeline-palette.card.html +4 -4
- package/components/_cards/radio.card.html +46 -0
- package/components/_cards/search.card.html +5 -2
- package/components/_cards/segmented-control.card.html +39 -0
- package/components/_cards/select.card.html +4 -4
- package/components/_cards/slider.card.html +1 -1
- package/components/_cards/smart-table.card.html +1 -1
- package/components/_cards/spreadsheet.card.html +2 -2
- package/components/_cards/stepper.card.html +2 -2
- package/components/_cards/table.card.html +103 -0
- package/components/_cards/tabs.card.html +3 -2
- package/components/_cards/tag.card.html +5 -2
- package/components/_cards/textarea.card.html +2 -2
- package/components/_cards/timeline.card.html +1 -1
- package/components/_cards/toast.card.html +4 -4
- package/components/_cards/toggles.card.html +45 -56
- package/components/_cards/tooltip.card.html +5 -5
- package/components/_cards/tree.card.html +2 -2
- package/components/_shared/src-buttons.js +1 -1
- package/components/_shared/src-charts.js +1 -1
- package/components/_shared/src-data.js +1 -1
- package/components/_shared/src-display.js +1 -1
- package/components/_shared/src-feedback.js +1 -1
- package/components/_shared/src-forms.js +1 -1
- package/components/_shared/src-navigation.js +1 -1
- package/components/_shared/src-pipeline.js +1 -1
- package/components/_shared/src-tabs.js +1 -1
- package/components/_shared/view-source.js +9 -4
- package/components/_vue/index.mjs +9 -5
- package/components/buttons/ActionChip.d.ts +3 -1
- package/components/buttons/ActionChip.jsx +4 -4
- package/components/buttons/ActionChip.vue +4 -4
- package/components/buttons/Button.d.ts +5 -2
- package/components/buttons/Button.jsx +15 -18
- package/components/buttons/Button.vue +17 -18
- package/components/buttons/ButtonGroup.vue +1 -1
- package/components/buttons/IconButton.d.ts +2 -1
- package/components/buttons/IconButton.jsx +9 -7
- package/components/buttons/IconButton.vue +10 -8
- package/components/buttons/buttons.prompt.md +6 -5
- package/components/charts/Bar3D.jsx +2 -2
- package/components/charts/Bar3D.vue +2 -2
- package/components/charts/BarChart.jsx +4 -4
- package/components/charts/BarChart.vue +4 -4
- package/components/charts/BarList.jsx +1 -1
- package/components/charts/BarList.vue +1 -1
- package/components/charts/BoxPlot.jsx +1 -1
- package/components/charts/BoxPlot.vue +2 -2
- package/components/charts/BulletChart.jsx +1 -1
- package/components/charts/BulletChart.vue +1 -1
- package/components/charts/CandlestickChart.jsx +2 -2
- package/components/charts/CandlestickChart.vue +3 -3
- package/components/charts/ChartKit.jsx +5 -5
- package/components/charts/ChartLegend.vue +16 -0
- package/components/charts/ChartTooltip.vue +16 -0
- package/components/charts/ChordChart.jsx +2 -2
- package/components/charts/ChordChart.vue +2 -2
- package/components/charts/GanttChart.jsx +2 -2
- package/components/charts/GanttChart.vue +2 -2
- package/components/charts/GaugeChart.jsx +2 -2
- package/components/charts/GaugeChart.vue +2 -2
- package/components/charts/HeatmapChart.jsx +2 -2
- package/components/charts/HeatmapChart.vue +2 -2
- package/components/charts/Histogram.jsx +2 -2
- package/components/charts/Histogram.vue +3 -3
- package/components/charts/LineChart.jsx +1 -1
- package/components/charts/LineChart.vue +3 -3
- package/components/charts/ParetoChart.jsx +3 -3
- package/components/charts/ParetoChart.vue +4 -4
- package/components/charts/PlotGrid.vue +18 -0
- package/components/charts/RadarChart.jsx +1 -1
- package/components/charts/RadarChart.vue +1 -1
- package/components/charts/Ribbon3D.jsx +2 -2
- package/components/charts/Ribbon3D.vue +2 -2
- package/components/charts/SankeyChart.jsx +2 -2
- package/components/charts/SankeyChart.vue +2 -2
- package/components/charts/Scatter3D.jsx +1 -1
- package/components/charts/Scatter3D.vue +1 -1
- package/components/charts/ScatterChart.jsx +3 -3
- package/components/charts/ScatterChart.vue +4 -4
- package/components/charts/Sparkline.jsx +1 -1
- package/components/charts/Sparkline.vue +1 -1
- package/components/charts/SunburstChart.jsx +1 -1
- package/components/charts/SunburstChart.vue +1 -1
- package/components/charts/Surface3D.jsx +2 -2
- package/components/charts/Surface3D.vue +2 -2
- package/components/charts/TreemapChart.jsx +2 -2
- package/components/charts/TreemapChart.vue +2 -2
- package/components/charts/WaterfallChart.jsx +2 -2
- package/components/charts/WaterfallChart.vue +3 -3
- package/components/charts/WorldMap.jsx +2 -2
- package/components/charts/WorldMap.vue +2 -2
- package/components/charts/XLabels.vue +11 -0
- package/components/data/CodeBlock.jsx +1 -1
- package/components/data/CodeBlock.vue +1 -1
- package/components/data/DiffValue.jsx +1 -1
- package/components/data/DiffValue.vue +1 -1
- package/components/data/FilterBar.d.ts +2 -0
- package/components/data/FilterBar.jsx +10 -9
- package/components/data/FilterBar.vue +9 -8
- package/components/data/KeyValue.jsx +3 -3
- package/components/data/KeyValue.vue +3 -3
- package/components/data/ListRow.jsx +2 -2
- package/components/data/ListRow.vue +2 -2
- package/components/data/Pagination.d.ts +5 -1
- package/components/data/Pagination.jsx +16 -12
- package/components/data/Pagination.vue +14 -9
- package/components/data/SmartTable.d.ts +4 -1
- package/components/data/SmartTable.jsx +16 -14
- package/components/data/SmartTable.vue +25 -22
- package/components/data/Spreadsheet.d.ts +2 -0
- package/components/data/Spreadsheet.jsx +12 -11
- package/components/data/Spreadsheet.vue +14 -13
- package/components/data/Table.d.ts +47 -0
- package/components/data/Table.jsx +85 -0
- package/components/data/Table.vue +63 -0
- package/components/data/data.prompt.md +3 -3
- package/components/display/Avatar.vue +3 -2
- package/components/display/AvatarGroup.vue +3 -2
- package/components/display/Badge.vue +1 -1
- package/components/display/Divider.vue +3 -3
- package/components/display/Donut.vue +3 -2
- package/components/display/IconTile.vue +2 -1
- package/components/display/Kbd.vue +1 -1
- package/components/display/ProgressBar.jsx +1 -1
- package/components/display/ProgressBar.vue +1 -1
- package/components/display/StatCard.vue +1 -1
- package/components/display/Tag.d.ts +3 -1
- package/components/display/Tag.jsx +4 -4
- package/components/display/Tag.vue +4 -4
- package/components/feedback/Accordion.jsx +2 -2
- package/components/feedback/Accordion.vue +2 -2
- package/components/feedback/ActivityItem.d.ts +3 -1
- package/components/feedback/ActivityItem.jsx +5 -5
- package/components/feedback/ActivityItem.vue +5 -4
- package/components/feedback/Alert.jsx +4 -4
- package/components/feedback/Alert.vue +3 -3
- package/components/feedback/Banner.jsx +5 -5
- package/components/feedback/Banner.vue +5 -5
- package/components/feedback/ContextMenu.d.ts +3 -1
- package/components/feedback/ContextMenu.jsx +5 -5
- package/components/feedback/ContextMenu.vue +5 -5
- package/components/feedback/DotActivity.vue +3 -3
- package/components/feedback/Drawer.d.ts +2 -0
- package/components/feedback/Drawer.jsx +6 -6
- package/components/feedback/Drawer.vue +22 -15
- package/components/feedback/EmptyState.vue +2 -2
- package/components/feedback/LogViewer.vue +1 -1
- package/components/feedback/Modal.d.ts +2 -0
- package/components/feedback/Modal.jsx +12 -11
- package/components/feedback/Modal.vue +10 -8
- package/components/feedback/Skeleton.vue +2 -1
- package/components/feedback/Spinner.vue +2 -1
- package/components/feedback/Stepper.vue +1 -1
- package/components/feedback/Timeline.jsx +1 -1
- package/components/feedback/Timeline.vue +1 -1
- package/components/feedback/Toast.vue +4 -4
- package/components/feedback/ToastStack.vue +11 -0
- package/components/feedback/Tooltip.vue +19 -0
- package/components/feedback/feedback.prompt.md +4 -4
- package/components/forms/Checkbox.d.ts +3 -2
- package/components/forms/Checkbox.jsx +7 -7
- package/components/forms/Checkbox.vue +8 -8
- package/components/forms/Combobox.d.ts +2 -0
- package/components/forms/Combobox.jsx +12 -10
- package/components/forms/Combobox.vue +11 -10
- package/components/forms/DatePicker.d.ts +4 -0
- package/components/forms/DatePicker.jsx +16 -12
- package/components/forms/DatePicker.vue +15 -11
- package/components/forms/Dropzone.jsx +2 -2
- package/components/forms/Dropzone.vue +5 -5
- package/components/forms/Field.d.ts +5 -1
- package/components/forms/Field.jsx +4 -4
- package/components/forms/Field.vue +4 -4
- package/components/forms/Input.d.ts +5 -1
- package/components/forms/Input.jsx +7 -7
- package/components/forms/Input.vue +3 -3
- package/components/forms/MultiSelect.d.ts +2 -0
- package/components/forms/MultiSelect.jsx +13 -11
- package/components/forms/MultiSelect.vue +12 -11
- package/components/forms/NumberStepper.d.ts +3 -1
- package/components/forms/NumberStepper.jsx +7 -7
- package/components/forms/NumberStepper.vue +8 -7
- package/components/forms/Radio.d.ts +30 -0
- package/components/forms/Radio.jsx +65 -0
- package/components/forms/Radio.vue +17 -9
- package/components/forms/RadioGroup.vue +22 -4
- package/components/forms/SearchInput.d.ts +3 -1
- package/components/forms/SearchInput.jsx +6 -6
- package/components/forms/SearchInput.vue +7 -6
- package/components/forms/Select.d.ts +3 -2
- package/components/forms/Select.jsx +6 -7
- package/components/forms/Select.vue +6 -6
- package/components/forms/Slider.jsx +3 -3
- package/components/forms/Slider.vue +3 -3
- package/components/forms/Switch.d.ts +32 -24
- package/components/forms/Switch.jsx +85 -35
- package/components/forms/Switch.vue +57 -11
- package/components/forms/Textarea.vue +4 -4
- package/components/forms/forms.prompt.md +4 -1
- package/components/forms/input-base.js +2 -1
- package/components/index.d.ts +2 -2
- package/components/index.js +5 -5
- package/components/navigation/Breadcrumb.jsx +3 -3
- package/components/navigation/Breadcrumb.vue +4 -4
- package/components/navigation/DocTree.jsx +3 -3
- package/components/navigation/DocTree.vue +3 -3
- package/components/navigation/PageHeading.vue +1 -1
- package/components/navigation/PageToolbar.vue +7 -6
- package/components/navigation/Sidebar.jsx +1 -1
- package/components/navigation/Sidebar.vue +3 -3
- package/components/navigation/ThemeToggle.vue +2 -1
- package/components/navigation/TopBar.d.ts +3 -1
- package/components/navigation/TopBar.jsx +6 -6
- package/components/navigation/Tree.jsx +5 -5
- package/components/navigation/Tree.vue +5 -5
- package/components/pipeline/ConfigPanel.d.ts +2 -0
- package/components/pipeline/ConfigPanel.jsx +9 -9
- package/components/pipeline/ConfigPanel.vue +9 -9
- package/components/pipeline/DataPreview.d.ts +3 -1
- package/components/pipeline/DataPreview.jsx +7 -7
- package/components/pipeline/DataPreview.vue +7 -7
- package/components/pipeline/NodeCard.jsx +3 -3
- package/components/pipeline/NodeCard.vue +3 -3
- package/components/pipeline/PaletteItem.vue +2 -2
- package/components/pipeline/PaletteListItem.vue +1 -1
- package/components/pipeline/PalettePanel.jsx +2 -2
- package/components/pipeline/PalettePanel.vue +1 -1
- package/components/pipeline/Port.vue +15 -0
- package/components/pipeline/PortLabel.vue +15 -0
- package/components/pipeline/ZoomControls.vue +1 -1
- package/components/pipeline/port-skin.js +13 -0
- package/components/px.js +4 -0
- package/components/tabs/PanelTabs.vue +5 -4
- package/components/tabs/PillTabs.vue +5 -4
- package/components/tabs/SegmentedControl.d.ts +11 -4
- package/components/tabs/SegmentedControl.jsx +25 -10
- package/components/tabs/SegmentedControl.vue +19 -7
- package/components/tabs/Tabs.d.ts +5 -3
- package/components/tabs/Tabs.jsx +15 -15
- package/components/tabs/Tabs.vue +5 -5
- package/components/tabs/ViewToggle.d.ts +3 -1
- package/components/tabs/ViewToggle.jsx +5 -5
- package/components/tabs/ViewToggle.vue +5 -5
- package/components/tabs/tabs.prompt.md +4 -2
- package/keybricks.css +4 -0
- package/package.json +6 -3
- package/readme.md +90 -123
- package/readme.zh-CN.md +120 -0
- package/tokens/charts.css +20 -17
- package/tokens/colors.css +2 -2
- package/tokens/dark.css +2 -2
- package/tokens/hover.css +32 -0
- package/tokens/interaction.css +3 -1
- package/tokens/layout.css +29 -7
- package/tokens/tokens.d.ts +36 -0
- package/tokens/tokens.js +143 -89
- package/tokens/tokens.json +240 -106
- package/tokens/typography.css +27 -14
- package/components/_cards/brand-visual.card.html +0 -43
- package/components/_cards/datatable.card.html +0 -48
- package/components/_shared/src-brand.js +0 -1
- package/components/brand/BrandVisual.d.ts +0 -17
- package/components/brand/BrandVisual.jsx +0 -29
- package/components/brand/BrandVisual.vue +0 -34
- package/components/brand/_dir.card.html +0 -13
- package/components/brand/brandMotifs.js +0 -210
- package/components/buttons/_dir.card.html +0 -13
- package/components/charts/ChartKit.vue +0 -47
- package/components/charts/_dir.card.html +0 -7
- package/components/data/DataTable.d.ts +0 -28
- package/components/data/DataTable.jsx +0 -32
- package/components/data/DataTable.vue +0 -25
- package/components/data/_dir.card.html +0 -13
- package/components/display/_dir.card.html +0 -13
- package/components/feedback/_dir.card.html +0 -13
- package/components/forms/_dir.card.html +0 -13
- package/components/icons/_dir.card.html +0 -13
- package/components/navigation/_dir.card.html +0 -13
- package/components/pipeline/_dir.card.html +0 -13
- package/components/tabs/_dir.card.html +0 -13
|
@@ -24,10 +24,10 @@ function pickHidden(it) { open.value = false; emit('select', it) }
|
|
|
24
24
|
function onDoc(e) { if (root.value && !root.value.contains(e.target)) open.value = false }
|
|
25
25
|
watch(open, (v) => { if (v) document.addEventListener('mousedown', onDoc); else document.removeEventListener('mousedown', onDoc) })
|
|
26
26
|
onUnmounted(() => document.removeEventListener('mousedown', onDoc))
|
|
27
|
-
const crumbStyle = (i, it) => ({ fontFamily: 'var(--font-sans)', fontSize: 'var(--text-
|
|
27
|
+
const crumbStyle = (i, it) => ({ fontFamily: 'var(--font-sans)', fontSize: 'var(--text-base)', lineHeight: 'var(--leading-base)', color: isLast(it) || on(i, it) ? 'var(--text-heading)' : 'var(--text-secondary)', fontWeight: isLast(it) ? 'var(--weight-medium)' : 'var(--weight-regular)', cursor: isLast(it) ? 'default' : 'pointer', borderRadius: 'var(--radius-sm)', transition: 'var(--t-hover)' })
|
|
28
28
|
</script>
|
|
29
29
|
<template>
|
|
30
|
-
<nav :style="{ display: 'flex', alignItems: 'center', gap:
|
|
30
|
+
<nav :style="{ display: 'flex', alignItems: 'center', gap: '4px', ...style }">
|
|
31
31
|
<template v-for="(it, i) in head" :key="it">
|
|
32
32
|
<span v-if="i > 0" style="color:var(--text-muted);display:inline-flex"><Icon name="chevron-right" :size="13" /></span>
|
|
33
33
|
<span :role="isLast(it) ? undefined : 'button'" :tabindex="isLast(it) ? undefined : 0"
|
|
@@ -40,14 +40,14 @@ const crumbStyle = (i, it) => ({ fontFamily: 'var(--font-sans)', fontSize: 'var(
|
|
|
40
40
|
<span role="button" tabindex="0" :aria-label="`Show ${hidden.length} hidden levels`" :aria-expanded="open"
|
|
41
41
|
@click="open = !open" @keydown.enter.prevent="open = !open" @keydown.space.prevent="open = !open" @keydown.esc="open = false"
|
|
42
42
|
@mouseenter="ovHover = true" @mouseleave="ovHover = false"
|
|
43
|
-
:style="{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: '
|
|
43
|
+
:style="{ display: 'inline-flex', alignItems: 'center', justifyContent: 'center', width: '24px', height: '24px', borderRadius: 'var(--radius-sm)', cursor: 'pointer', color: open || ovHover ? 'var(--text-heading)' : 'var(--text-muted)', background: open ? 'var(--bg-active)' : ovHover ? 'var(--bg-hover)' : 'transparent', transition: 'var(--t-hover)' }">
|
|
44
44
|
<Icon name="ellipsis" :size="14" />
|
|
45
45
|
</span>
|
|
46
46
|
<span v-if="open" style="position:absolute;top:calc(100% + 5px);left:0;z-index:var(--z-menu);min-width:168px;max-width:260px;background:var(--bg-surface);border:1px solid var(--border-card);border-radius:var(--radius-md);box-shadow:var(--shadow-menu);padding:4px;display:flex;flex-direction:column">
|
|
47
47
|
<span v-for="(h, hi) in hidden" :key="h" role="menuitem" tabindex="0"
|
|
48
48
|
@click="pickHidden(h)" @keydown.enter.prevent="pickHidden(h)" @keydown.space.prevent="pickHidden(h)"
|
|
49
49
|
@mouseenter="menuHover = hi" @mouseleave="menuHover = -1"
|
|
50
|
-
:style="{ display: 'flex', alignItems: 'center', gap: '6px', padding: '6px 9px', paddingLeft: (9 + hi * 12) + 'px', borderRadius: 'var(--radius-sm)', cursor: 'pointer', background: menuHover === hi ? 'var(--bg-hover)' : 'transparent', fontFamily: 'var(--font-sans)', fontSize: 'var(--text-
|
|
50
|
+
:style="{ display: 'flex', alignItems: 'center', gap: '6px', padding: '6px 9px', paddingLeft: (9 + hi * 12) + 'px', borderRadius: 'var(--radius-sm)', cursor: 'pointer', background: menuHover === hi ? 'var(--bg-hover)' : 'transparent', fontFamily: 'var(--font-sans)', fontSize: 'var(--text-base)', lineHeight: 'var(--leading-base)', color: 'var(--text-heading)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis', transition: 'var(--t-hover)' }">
|
|
51
51
|
<span v-if="hi > 0" style="color:var(--text-muted);display:inline-flex;flex-shrink:0"><Icon name="chevron-right" :size="11" /></span>{{ h }}
|
|
52
52
|
</span>
|
|
53
53
|
</span>
|
|
@@ -20,14 +20,14 @@ export function DocTree({ title = "Documents", items = [], active, onSelect, sty
|
|
|
20
20
|
{items.map((it) => {
|
|
21
21
|
const is = active === it.label;
|
|
22
22
|
return (
|
|
23
|
-
<div key={it.label} role="treeitem" tabIndex={0} onClick={() => onSelect && onSelect(it.label)}
|
|
24
|
-
style={{ height: "var(--h-tree-item)", borderRadius: "var(--radius-md)", display: "flex", alignItems: "center", gap: 8, padding: "6px 8px", boxSizing: "border-box", cursor: "pointer", background: is ? "var(--bg-active)" : "transparent" }}
|
|
23
|
+
<div key={it.label} role="treeitem" tabIndex={0} data-wash={is ? undefined : ""} onClick={() => onSelect && onSelect(it.label)}
|
|
24
|
+
style={{ height: "var(--h-tree-item)", borderRadius: "var(--radius-md)", display: "flex", alignItems: "center", gap: 8, padding: "6px 8px", boxSizing: "border-box", cursor: "pointer", background: is ? "var(--bg-active)" : "var(--wash, transparent)", transition: "var(--t-hover)" }}
|
|
25
25
|
onMouseEnter={(e) => { if (!is) e.currentTarget.style.background = "var(--bg-hover)"; }}
|
|
26
26
|
onMouseLeave={(e) => { if (!is) e.currentTarget.style.background = "transparent"; }}>
|
|
27
27
|
<span style={{ color: it.kind === "folder" ? "var(--text-muted)" : docHues[it.hue || "gray"], display: "inline-flex" }}>
|
|
28
28
|
<Icon name={it.icon || (it.kind === "folder" ? "folder" : "file-text")} size={16} />
|
|
29
29
|
</span>
|
|
30
|
-
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-
|
|
30
|
+
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", color: "var(--text-heading)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{it.label}</span>
|
|
31
31
|
</div>
|
|
32
32
|
);
|
|
33
33
|
})}
|
|
@@ -15,10 +15,10 @@ const emit = defineEmits(['select'])
|
|
|
15
15
|
</div>
|
|
16
16
|
<div style="padding:12px 16px 8px;border-bottom:1px solid var(--border-subtle)"><SearchInput bare placeholder="Search..." style="gap:8px" /></div>
|
|
17
17
|
<div style="padding:8px;display:flex;flex-direction:column;gap:2px;overflow-y:auto">
|
|
18
|
-
<div v-for="it in items" :key="it.label" @click="emit('select', it.label)"
|
|
19
|
-
:style="{ height: 'var(--h-tree-item)', borderRadius: 'var(--radius-md)', display: 'flex', alignItems: 'center', gap:
|
|
18
|
+
<div v-for="it in items" :key="it.label" role="treeitem" tabindex="0" @click="emit('select', it.label)" @keydown.enter="emit('select', it.label)"
|
|
19
|
+
:style="{ height: 'var(--h-tree-item)', borderRadius: 'var(--radius-md)', display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 8px', boxSizing: 'border-box', cursor: 'pointer', background: active === it.label ? 'var(--bg-active)' : 'var(--wash, transparent)', transition: 'var(--t-hover)' }" :data-wash="active === it.label ? undefined : ''">
|
|
20
20
|
<span :style="{ color: it.kind === 'folder' ? 'var(--text-muted)' : docHues[it.hue || 'gray'], display: 'inline-flex' }"><Icon :name="it.icon || (it.kind === 'folder' ? 'folder' : 'file-text')" :size="16" /></span>
|
|
21
|
-
<span style="font-family:var(--font-sans);font-size:var(--text-
|
|
21
|
+
<span style="font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--leading-base);color:var(--text-heading);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ it.label }}</span>
|
|
22
22
|
</div>
|
|
23
23
|
</div>
|
|
24
24
|
</div>
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
defineProps({ title: String, subtitle: String, style: Object })
|
|
3
3
|
</script>
|
|
4
4
|
<template>
|
|
5
|
-
<div :style="{ display: 'flex', flexDirection: 'column', gap:
|
|
5
|
+
<div :style="{ display: 'flex', flexDirection: 'column', gap: '4px', ...style }">
|
|
6
6
|
<span style="font-family:var(--font-sans);font-weight:var(--weight-medium);font-size:var(--text-lg);line-height:var(--leading-lg);letter-spacing:var(--tracking-lg);color:var(--text-primary)">{{ title }}</span>
|
|
7
7
|
<span v-if="subtitle" style="font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-secondary)">{{ subtitle }}</span>
|
|
8
8
|
</div>
|
|
@@ -1,15 +1,16 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import IconButton from '../buttons/IconButton.vue'
|
|
3
|
-
|
|
3
|
+
// Page toolbar under the top bar: back · title · status, actions on the right. A size region (default inherit → md).
|
|
4
|
+
defineProps({ title: String, status: { type: String, default: '• Editing' }, showBack: Boolean, size: String, style: Object })
|
|
4
5
|
const emit = defineEmits(['back'])
|
|
5
6
|
</script>
|
|
6
7
|
<template>
|
|
7
|
-
<div :style="{ height: 'var(--topbar-h)', background: 'var(--bg-surface)', borderBottom: '1px solid var(--border-card)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0
|
|
8
|
-
<div style="display:flex;align-items:center;gap:
|
|
9
|
-
<IconButton v-if="showBack" icon="chevron-left"
|
|
8
|
+
<div :data-size="size" :style="{ height: 'var(--topbar-h)', background: 'var(--bg-surface)', borderBottom: '1px solid var(--border-card)', display: 'flex', alignItems: 'center', justifyContent: 'space-between', padding: '0 var(--edge-pad)', boxSizing: 'border-box', flexShrink: 0, ...style }">
|
|
9
|
+
<div style="display:flex;align-items:center;gap:var(--control-gap)">
|
|
10
|
+
<IconButton v-if="showBack" icon="chevron-left" label="Back" @click="emit('back')" />
|
|
10
11
|
<span style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-md);line-height:var(--leading-md);letter-spacing:var(--tracking-md);color:var(--text-heading)">{{ title }}</span>
|
|
11
|
-
<span v-if="status" style="font-family:var(--font-sans);font-size:var(--text
|
|
12
|
+
<span v-if="status" style="font-family:var(--font-sans);font-size:var(--control-text);line-height:var(--control-leading);letter-spacing:var(--control-tracking);color:var(--text-muted);margin-left:6px">{{ status }}</span>
|
|
12
13
|
</div>
|
|
13
|
-
<div style="display:flex;align-items:center;gap:
|
|
14
|
+
<div style="display:flex;align-items:center;gap:var(--control-gap)"><slot name="actions" /></div>
|
|
14
15
|
</div>
|
|
15
16
|
</template>
|
|
@@ -30,7 +30,7 @@ export function Sidebar({ items = [], footerItems = [{ icon: "circle-help", labe
|
|
|
30
30
|
{onToggleCollapse ? <NavItem icon="panel-left" label="Collapse" collapsed={collapsed} onClick={onToggleCollapse} /> : null}
|
|
31
31
|
{items.map((it) => it.children ? (
|
|
32
32
|
<div key={it.label}>
|
|
33
|
-
<div onClick={() => toggleSection(it.label)} style={{ height: "var(--h-subnav-item)", display: "flex", alignItems: "center", gap: 10, padding: collapsed ? "6px 10px" : "6px 10px", justifyContent: collapsed ? "center" : "flex-start", cursor: "pointer", color: "var(--text-body)", borderRadius: "var(--radius-md)", boxSizing: "border-box" }}>
|
|
33
|
+
<div role="button" tabIndex={0} data-wash="" onClick={() => toggleSection(it.label)} onKeyDown={(e) => { if (e.key === "Enter" || e.key === " ") { e.preventDefault(); toggleSection(it.label); } }} style={{ background: "var(--wash, transparent)", transition: "var(--t-hover)", height: "var(--h-subnav-item)", display: "flex", alignItems: "center", gap: 10, padding: collapsed ? "6px 10px" : "6px 10px", justifyContent: collapsed ? "center" : "flex-start", cursor: "pointer", color: "var(--text-body)", borderRadius: "var(--radius-md)", boxSizing: "border-box" }}>
|
|
34
34
|
<Icon name={it.icon} size={16} />
|
|
35
35
|
{!collapsed ? <><span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-medium)", fontSize: "var(--text-base)", letterSpacing: "var(--tracking-base)", flex: 1 }}>{it.label}</span><Icon name={openSections.includes(it.label) ? "chevron-up" : "chevron-down"} size={14} /></> : null}
|
|
36
36
|
</div>
|
|
@@ -16,11 +16,11 @@ const props = defineProps({
|
|
|
16
16
|
const emit = defineEmits(['select', 'toggleCollapse'])
|
|
17
17
|
const openSections = ref(props.items.filter(i => i.children && (i.open || i.children.some(c => c.label === props.active))).map(i => i.label))
|
|
18
18
|
function toggleSection(l) { openSections.value = openSections.value.includes(l) ? openSections.value.filter(x => x !== l) : [...openSections.value, l] }
|
|
19
|
-
function itemStyle(active, indent) { return { height: indent ? 'var(--h-subnav-item)' : 'var(--h-nav-item)', borderRadius: 'var(--radius-md)', display: 'flex', alignItems: 'center', gap:
|
|
19
|
+
function itemStyle(active, indent) { return { height: indent ? 'var(--h-subnav-item)' : 'var(--h-nav-item)', borderRadius: 'var(--radius-md)', display: 'flex', alignItems: 'center', gap: '10px', padding: indent ? '6px 10px' : '8px 10px', boxSizing: 'border-box', cursor: 'pointer', background: active ? 'var(--bg-active)' : 'transparent', color: active ? 'var(--text-heading)' : 'var(--text-body)', transition: 'var(--t-hover)' } }
|
|
20
20
|
</script>
|
|
21
21
|
<template>
|
|
22
22
|
<aside :style="{ width: collapsed ? 'var(--rail-w)' : 'var(--sidebar-w)', height, background: 'var(--bg-surface)', borderRight: '1px solid var(--border-card)', display: 'flex', flexDirection: 'column', boxSizing: 'border-box', flexShrink: 0, transition: 'width .15s ease', ...style }">
|
|
23
|
-
<div :style="{ height: 'var(--topbar-h)', borderBottom: '1px solid var(--border-card)', display: 'flex', alignItems: 'center', gap:
|
|
23
|
+
<div :style="{ height: 'var(--topbar-h)', borderBottom: '1px solid var(--border-card)', display: 'flex', alignItems: 'center', gap: '10px', padding: '0 16px', boxSizing: 'border-box', justifyContent: collapsed ? 'center' : 'flex-start', flexShrink: 0 }">
|
|
24
24
|
<img :src="logo" alt="" style="width:24px;height:24px;object-fit:contain" />
|
|
25
25
|
<span v-if="!collapsed" style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-lg);line-height:var(--leading-lg);letter-spacing:-.609px;color:var(--text-primary)">{{ brand }}</span>
|
|
26
26
|
</div>
|
|
@@ -28,7 +28,7 @@ function itemStyle(active, indent) { return { height: indent ? 'var(--h-subnav-i
|
|
|
28
28
|
<div v-if="canCollapse" role="button" tabindex="0" @click="emit('toggleCollapse')" :style="itemStyle(false, false)"><Icon name="panel-left" :size="16" /><span v-if="!collapsed" style="font-family:var(--font-sans);font-weight:var(--weight-medium);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);white-space:nowrap;flex:1">Collapse</span></div>
|
|
29
29
|
<template v-for="it in items" :key="it.label">
|
|
30
30
|
<div v-if="it.children">
|
|
31
|
-
<div role="button" tabindex="0" @click="toggleSection(it.label)" :style="{ height: 'var(--h-subnav-item)', display: 'flex', alignItems: 'center', gap:
|
|
31
|
+
<div role="button" tabindex="0" data-wash="" @click="toggleSection(it.label)" @keydown.enter.prevent="toggleSection(it.label)" @keydown.space.prevent="toggleSection(it.label)" :style="{ background: 'var(--wash, transparent)', transition: 'var(--t-hover)', height: 'var(--h-subnav-item)', display: 'flex', alignItems: 'center', gap: '10px', padding: '6px 10px', justifyContent: collapsed ? 'center' : 'flex-start', cursor: 'pointer', color: 'var(--text-body)', borderRadius: 'var(--radius-md)', boxSizing: 'border-box' }">
|
|
32
32
|
<Icon :name="it.icon" :size="16" />
|
|
33
33
|
<template v-if="!collapsed"><span style="font-family:var(--font-sans);font-weight:var(--weight-medium);font-size:var(--text-base);letter-spacing:var(--tracking-base);flex:1">{{ it.label }}</span><Icon :name="openSections.includes(it.label) ? 'chevron-up' : 'chevron-down'" :size="14" /></template>
|
|
34
34
|
</div>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
+
import { px } from '../px.js'
|
|
2
3
|
import { ref, computed, watch, onMounted } from 'vue'
|
|
3
4
|
import Icon from '../icons/Icon.vue'
|
|
4
5
|
const props = defineProps({ size: { type: Number, default: 34 }, dark: { type: Boolean, default: null }, style: Object })
|
|
@@ -12,7 +13,7 @@ function toggle() { if (props.dark != null) emit('update:dark', !dark.value); el
|
|
|
12
13
|
</script>
|
|
13
14
|
<template>
|
|
14
15
|
<button type="button" :aria-label="dark ? 'Switch to light mode' : 'Switch to dark mode'" @click="toggle" @mouseenter="hover = true" @mouseleave="hover = false"
|
|
15
|
-
:style="{ width: size, height: size, borderRadius: 'var(--radius-md)', border: 'none', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', background: hover ? 'var(--bg-hover)' : 'transparent', color: 'var(--text-body)', padding: 0, transition: 'var(--t-hover)', ...style }">
|
|
16
|
+
:style="{ width: px(size), height: px(size), borderRadius: 'var(--radius-md)', border: 'none', cursor: 'pointer', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', background: hover ? 'var(--bg-hover)' : 'transparent', color: 'var(--text-body)', padding: 0, transition: 'var(--t-hover)', ...style }">
|
|
16
17
|
<Icon :name="dark ? 'sparkles' : 'moon'" :size="18" />
|
|
17
18
|
</button>
|
|
18
19
|
</template>
|
|
@@ -15,10 +15,12 @@ export interface PageToolbarProps {
|
|
|
15
15
|
status?: string;
|
|
16
16
|
actions?: React.ReactNode;
|
|
17
17
|
onBack?: () => void;
|
|
18
|
+
/** Size tier for the toolbar's controls. Omit to inherit (the default). */
|
|
19
|
+
size?: "sm" | "md" | "lg";
|
|
18
20
|
style?: React.CSSProperties;
|
|
19
21
|
}
|
|
20
22
|
export declare function PageToolbar(props: PageToolbarProps): JSX.Element;
|
|
21
|
-
/**
|
|
23
|
+
/** Page title (--text-lg 20px/500) + muted subtitle. */
|
|
22
24
|
export interface PageHeadingProps {
|
|
23
25
|
title?: string;
|
|
24
26
|
subtitle?: string;
|
|
@@ -20,15 +20,15 @@ export function TopBar({ placeholder = "Search documents, workflows, data...", a
|
|
|
20
20
|
}
|
|
21
21
|
|
|
22
22
|
/** Editor toolbar: back chevron, 14px/600 title, "• Editing" status, right action slot. */
|
|
23
|
-
export function PageToolbar({ title, status = "• Editing", actions, onBack, style }) {
|
|
23
|
+
export function PageToolbar({ title, status = "• Editing", actions, onBack, size, style }) {
|
|
24
24
|
return (
|
|
25
|
-
<div style={{ height: "var(--topbar-h)", background: "var(--bg-surface)", borderBottom: "1px solid var(--border-card)", display: "flex", alignItems: "center", justifyContent: "space-between", padding: "0
|
|
26
|
-
<div style={{ display: "flex", alignItems: "center", gap:
|
|
27
|
-
{onBack ? <IconButton icon="chevron-left"
|
|
25
|
+
<div data-size={size} style={{ height: "var(--topbar-h)", background: "var(--bg-surface)", borderBottom: "1px solid var(--border-card)", display: "flex", alignItems: "center", justifyContent: "space-between", padding: "0 var(--edge-pad)", boxSizing: "border-box", flexShrink: 0, ...style }}>
|
|
26
|
+
<div style={{ display: "flex", alignItems: "center", gap: "var(--control-gap)" }}>
|
|
27
|
+
{onBack ? <IconButton icon="chevron-left" onClick={onBack} label="Back" /> : null}
|
|
28
28
|
<span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-semibold)", fontSize: "var(--text-md)", lineHeight: "var(--leading-md)", letterSpacing: "var(--tracking-md)", color: "var(--text-heading)" }}>{title}</span>
|
|
29
|
-
{status ? <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text
|
|
29
|
+
{status ? <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--control-text)", lineHeight: "var(--control-leading)", letterSpacing: "var(--control-tracking)", color: "var(--text-muted)", marginLeft: 6 }}>{status}</span> : null}
|
|
30
30
|
</div>
|
|
31
|
-
<div style={{ display: "flex", alignItems: "center", gap:
|
|
31
|
+
<div style={{ display: "flex", alignItems: "center", gap: "var(--control-gap)" }}>{actions}</div>
|
|
32
32
|
</div>
|
|
33
33
|
);
|
|
34
34
|
}
|
|
@@ -153,7 +153,7 @@ function Row({ item, state, cfg, api }) {
|
|
|
153
153
|
{chevron}
|
|
154
154
|
{cfg.checkable && node.checkable !== false ? (
|
|
155
155
|
<span onClick={(e) => e.stopPropagation()} style={{ display: "inline-flex", flexShrink: 0 }}>
|
|
156
|
-
<Checkbox
|
|
156
|
+
<Checkbox checked={checked} indeterminate={half} disabled={disabled || node.disableCheckbox} onChange={() => api.check(key)} />
|
|
157
157
|
</span>
|
|
158
158
|
) : null}
|
|
159
159
|
{cfg.showIcon ? (
|
|
@@ -161,11 +161,11 @@ function Row({ item, state, cfg, api }) {
|
|
|
161
161
|
<Icon name={node.icon || (branch ? (open ? "folder-open" : "folder") : "file-text")} size={15} />
|
|
162
162
|
</span>
|
|
163
163
|
) : null}
|
|
164
|
-
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-
|
|
164
|
+
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", fontWeight: selected ? "var(--weight-medium)" : "var(--weight-regular)", color: disabled ? "var(--text-muted)" : "var(--text-heading)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>
|
|
165
165
|
<Highlight text={titleOf(node)} query={cfg.searchValue} />
|
|
166
166
|
</span>
|
|
167
|
-
{node.tag ? <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-
|
|
168
|
-
{node.count != null ? <span style={{ marginLeft: "auto", fontFamily: "var(--font-mono)", fontSize: "var(--text-
|
|
167
|
+
{node.tag ? <span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", lineHeight: 1, padding: "2px 5px", borderRadius: "var(--radius-sm)", background: "var(--bg-inset)", color: "var(--text-secondary)", flexShrink: 0 }}>{node.tag}</span> : null}
|
|
168
|
+
{node.count != null ? <span style={{ marginLeft: "auto", fontFamily: "var(--font-mono)", fontSize: "var(--text-xs)", color: "var(--text-muted)", paddingLeft: 8 }}>{node.count}</span> : null}
|
|
169
169
|
{cfg.rowActions && !disabled ? <span style={{ marginLeft: node.count != null ? 6 : "auto", display: "flex", gap: 2, opacity: hover ? 1 : 0, transition: "var(--t-hover)" }} onClick={(e) => e.stopPropagation()}>{cfg.rowActions(node)}</span> : null}
|
|
170
170
|
</div>
|
|
171
171
|
{open && loading && !kids.length ? (
|
|
@@ -340,7 +340,7 @@ export function Tree({
|
|
|
340
340
|
<div role="tree" aria-multiselectable={multiple || undefined} style={{ display: "flex", flexDirection: "column", gap: showLine ? 0 : 1, ...style }}>
|
|
341
341
|
<style>{"@keyframes kb-tree-spin{to{transform:rotate(360deg)}}"}</style>
|
|
342
342
|
{rows.length === 0 ? (
|
|
343
|
-
<div style={{ padding: "10px 8px", fontFamily: "var(--font-sans)", fontSize: "var(--text-
|
|
343
|
+
<div style={{ padding: "10px 8px", fontFamily: "var(--font-sans)", fontSize: "var(--text-base)", color: "var(--text-muted)" }}>No matching items</div>
|
|
344
344
|
) : rows.map((r) => <Row key={r.key} item={r} state={state} cfg={cfg} api={api} />)}
|
|
345
345
|
</div>
|
|
346
346
|
);
|
|
@@ -235,19 +235,19 @@ const dropAt = k => (drop.value && drop.value.key === k ? drop.value.pos : null)
|
|
|
235
235
|
</span>
|
|
236
236
|
<span v-else :style="{ width: showLine ? 0 : '14px', flexShrink: 0 }" />
|
|
237
237
|
<span v-if="checkable && row.n.checkable !== false" @click.stop style="display:inline-flex;flex-shrink:0">
|
|
238
|
-
<Checkbox
|
|
238
|
+
<Checkbox :checked="view.full.has(row.key)" :indeterminate="view.half.has(row.key)"
|
|
239
239
|
:disabled="row.n.disabled || row.n.disableCheckbox" @change="check(row.key)" />
|
|
240
240
|
</span>
|
|
241
241
|
<span v-if="showIcon" :style="{ color: isBranch(row.n) ? 'var(--text-muted)' : docHues[row.n.hue || 'gray'], display: 'inline-flex', flexShrink: 0 }">
|
|
242
242
|
<Icon :name="row.n.icon || (isBranch(row.n) ? (openKeys.includes(row.key) ? 'folder-open' : 'folder') : 'file-text')" :size="15" />
|
|
243
243
|
</span>
|
|
244
|
-
<span :style="{ fontFamily: 'var(--font-sans)', fontSize: 'var(--text-
|
|
244
|
+
<span :style="{ fontFamily: 'var(--font-sans)', fontSize: 'var(--text-base)', lineHeight: 'var(--leading-base)', fontWeight: selected.includes(row.key) ? 'var(--weight-medium)' : 'var(--weight-regular)', color: row.n.disabled ? 'var(--text-muted)' : 'var(--text-heading)', whiteSpace: 'nowrap', overflow: 'hidden', textOverflow: 'ellipsis' }">
|
|
245
245
|
<template v-for="(p, i) in parts(titleOf(row.n))" :key="i"><mark v-if="p.hit" style="background:var(--soft-bg);color:var(--info-fg);font-weight:var(--weight-medium);padding:0;border-radius:2px">{{ p.t }}</mark><template v-else>{{ p.t }}</template></template>
|
|
246
246
|
</span>
|
|
247
|
-
<span v-if="row.n.tag" style="font-family:var(--font-sans);font-size:var(--text-
|
|
248
|
-
<span v-if="row.n.count != null" style="margin-left:auto;font-family:var(--font-mono);font-size:var(--text-
|
|
247
|
+
<span v-if="row.n.tag" style="font-family:var(--font-sans);font-size:var(--text-xs);line-height:1;padding:2px 5px;border-radius:var(--radius-sm);background:var(--bg-inset);color:var(--text-secondary);flex-shrink:0">{{ row.n.tag }}</span>
|
|
248
|
+
<span v-if="row.n.count != null" style="margin-left:auto;font-family:var(--font-mono);font-size:var(--text-xs);color:var(--text-muted);padding-left:8px">{{ row.n.count }}</span>
|
|
249
249
|
</div>
|
|
250
|
-
<div v-if="!rows.length" style="padding:10px 8px;font-family:var(--font-sans);font-size:var(--text-
|
|
250
|
+
<div v-if="!rows.length" style="padding:10px 8px;font-family:var(--font-sans);font-size:var(--text-base);color:var(--text-muted)">No matching items</div>
|
|
251
251
|
</div>
|
|
252
252
|
</template>
|
|
253
253
|
<style scoped>
|
|
@@ -13,6 +13,8 @@ export interface ConfigPanelProps {
|
|
|
13
13
|
onPreview?: () => void;
|
|
14
14
|
children?: React.ReactNode;
|
|
15
15
|
height?: number | string;
|
|
16
|
+
/** Size tier for the panel's controls. Omit to inherit (→ md). */
|
|
17
|
+
size?: "sm" | "md" | "lg";
|
|
16
18
|
style?: React.CSSProperties;
|
|
17
19
|
}
|
|
18
20
|
export declare function ConfigPanel(props: ConfigPanelProps): JSX.Element;
|
|
@@ -3,24 +3,24 @@ import { Button } from "../buttons/Button.jsx";
|
|
|
3
3
|
import { PanelTabs } from "../tabs/Tabs.jsx";
|
|
4
4
|
import { NumberStepper } from "../forms/NumberStepper.jsx";
|
|
5
5
|
|
|
6
|
-
/** Right node-config panel — 400px: title/subtitle + Save Settings, preview-rows row, PanelTabs, body slot. */
|
|
7
|
-
export function ConfigPanel({ title, subtitle, tabs = ["Node Info", "Calc Rules", "Output Fields", "SQL Preview"], activeTab, onTab, previewRows = 100, onPreviewRows, onSave, onPreview, children, height = "100%", style }) {
|
|
6
|
+
/** Right node-config panel — 400px: title/subtitle + Save Settings, preview-rows row, PanelTabs, body slot. A size region (default inherit → md): every control in the header shares one tier. */
|
|
7
|
+
export function ConfigPanel({ title, subtitle, tabs = ["Node Info", "Calc Rules", "Output Fields", "SQL Preview"], activeTab, onTab, previewRows = 100, onPreviewRows, onSave, onPreview, children, height = "100%", size, style }) {
|
|
8
8
|
const [tab, setTab] = React.useState(tabs[0]);
|
|
9
9
|
const cur = activeTab != null ? activeTab : tab;
|
|
10
10
|
return (
|
|
11
|
-
<div style={{ width: "var(--panel-w)", height, background: "var(--bg-surface)", borderLeft: "1px solid var(--border-card)", display: "flex", flexDirection: "column", boxSizing: "border-box", flexShrink: 0, ...style }}>
|
|
11
|
+
<div data-size={size} style={{ width: "var(--panel-w)", height, background: "var(--bg-surface)", borderLeft: "1px solid var(--border-card)", display: "flex", flexDirection: "column", boxSizing: "border-box", flexShrink: 0, ...style }}>
|
|
12
12
|
<div style={{ padding: "12px 16px 0", borderBottom: "1px solid var(--border-card)", flexShrink: 0 }}>
|
|
13
13
|
<div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-start" }}>
|
|
14
14
|
<div style={{ display: "flex", flexDirection: "column" }}>
|
|
15
|
-
<span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-semibold)", fontSize: "var(--text-md)", lineHeight: "
|
|
16
|
-
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", lineHeight: "var(--leading-xs)", letterSpacing: "var(--tracking-xs)", color: "var(--text-muted)", paddingTop:
|
|
15
|
+
<span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-semibold)", fontSize: "var(--text-md)", lineHeight: "var(--leading-md)", letterSpacing: "var(--tracking-md)", color: "var(--text-heading)" }}>{title}</span>
|
|
16
|
+
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", lineHeight: "var(--leading-xs)", letterSpacing: "var(--tracking-xs)", color: "var(--text-muted)", paddingTop: 2 }}>{subtitle}</span>
|
|
17
17
|
</div>
|
|
18
|
-
<Button
|
|
18
|
+
<Button onClick={onSave}>Save Settings</Button>
|
|
19
19
|
</div>
|
|
20
|
-
<div style={{ display: "flex", alignItems: "center", gap:
|
|
21
|
-
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text
|
|
20
|
+
<div style={{ display: "flex", alignItems: "center", gap: "var(--control-gap)", padding: "12px 0" }}>
|
|
21
|
+
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--control-text)", lineHeight: "var(--control-leading)", letterSpacing: "var(--control-tracking)", color: "var(--text-secondary)" }}>Preview rows</span>
|
|
22
22
|
<NumberStepper value={previewRows} onChange={onPreviewRows} />
|
|
23
|
-
<Button variant="primary-soft"
|
|
23
|
+
<Button variant="primary-soft" icon="eye" onClick={onPreview}>Data Preview</Button>
|
|
24
24
|
</div>
|
|
25
25
|
<PanelTabs tabs={tabs} active={cur} onChange={(t) => { setTab(t); onTab && onTab(t); }} style={{ margin: "0 -16px", padding: "0 16px", borderBottom: "none" }} />
|
|
26
26
|
</div>
|
|
@@ -3,27 +3,27 @@ import { ref, computed } from 'vue'
|
|
|
3
3
|
import Button from '../buttons/Button.vue'
|
|
4
4
|
import PanelTabs from '../tabs/Tabs.vue'
|
|
5
5
|
import NumberStepper from '../forms/NumberStepper.vue'
|
|
6
|
-
// Right node-config panel — 400px: title/subtitle + Save Settings, preview-rows row, PanelTabs, body slot.
|
|
7
|
-
const props = defineProps({ title: String, subtitle: String, tabs: { type: Array, default: () => ['Node Info', 'Calc Rules', 'Output Fields', 'SQL Preview'] }, activeTab: String, previewRows: { type: Number, default: 100 }, height: { type: [String, Number], default: '100%' }, style: Object })
|
|
6
|
+
// Right node-config panel — 400px: title/subtitle + Save Settings, preview-rows row, PanelTabs, body slot. A size region (default inherit → md): every control in the header shares one tier.
|
|
7
|
+
const props = defineProps({ title: String, subtitle: String, tabs: { type: Array, default: () => ['Node Info', 'Calc Rules', 'Output Fields', 'SQL Preview'] }, activeTab: String, previewRows: { type: Number, default: 100 }, height: { type: [String, Number], default: '100%' }, size: String, style: Object })
|
|
8
8
|
const emit = defineEmits(['tab', 'update:previewRows', 'save', 'preview'])
|
|
9
9
|
const tabState = ref(props.tabs[0])
|
|
10
10
|
const cur = computed(() => props.activeTab != null ? props.activeTab : tabState.value)
|
|
11
11
|
function setTab(t) { tabState.value = t; emit('tab', t) }
|
|
12
12
|
</script>
|
|
13
13
|
<template>
|
|
14
|
-
<div :style="{ width: 'var(--panel-w)', height, background: 'var(--bg-surface)', borderLeft: '1px solid var(--border-card)', display: 'flex', flexDirection: 'column', boxSizing: 'border-box', flexShrink: 0, ...style }">
|
|
14
|
+
<div :data-size="size" :style="{ width: 'var(--panel-w)', height, background: 'var(--bg-surface)', borderLeft: '1px solid var(--border-card)', display: 'flex', flexDirection: 'column', boxSizing: 'border-box', flexShrink: 0, ...style }">
|
|
15
15
|
<div style="padding:12px 16px 0;border-bottom:1px solid var(--border-card);flex-shrink:0">
|
|
16
16
|
<div style="display:flex;justify-content:space-between;align-items:flex-start">
|
|
17
17
|
<div style="display:flex;flex-direction:column">
|
|
18
|
-
<span style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-md);line-height:
|
|
19
|
-
<span style="font-family:var(--font-sans);font-size:var(--text-xs);line-height:var(--leading-xs);letter-spacing:var(--tracking-xs);color:var(--text-muted);padding-top:
|
|
18
|
+
<span style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-md);line-height:var(--leading-md);letter-spacing:var(--tracking-md);color:var(--text-heading)">{{ title }}</span>
|
|
19
|
+
<span style="font-family:var(--font-sans);font-size:var(--text-xs);line-height:var(--leading-xs);letter-spacing:var(--tracking-xs);color:var(--text-muted);padding-top:2px">{{ subtitle }}</span>
|
|
20
20
|
</div>
|
|
21
|
-
<Button
|
|
21
|
+
<Button @click="emit('save')">Save Settings</Button>
|
|
22
22
|
</div>
|
|
23
|
-
<div style="display:flex;align-items:center;gap:
|
|
24
|
-
<span style="font-family:var(--font-sans);font-size:var(--text
|
|
23
|
+
<div style="display:flex;align-items:center;gap:var(--control-gap);padding:12px 0">
|
|
24
|
+
<span style="font-family:var(--font-sans);font-size:var(--control-text);line-height:var(--control-leading);letter-spacing:var(--control-tracking);color:var(--text-secondary)">Preview rows</span>
|
|
25
25
|
<NumberStepper :model-value="previewRows" @update:modelValue="v => emit('update:previewRows', v)" />
|
|
26
|
-
<Button variant="primary-soft"
|
|
26
|
+
<Button variant="primary-soft" icon="eye" @click="emit('preview')">Data Preview</Button>
|
|
27
27
|
</div>
|
|
28
28
|
<PanelTabs :tabs="tabs" :active="cur" @change="setTab" style="margin:0 -16px;padding:0 16px;border-bottom:none" />
|
|
29
29
|
</div>
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
import { DataTableColumn } from "../data/
|
|
2
|
+
import { DataTableColumn } from "../data/Table";
|
|
3
3
|
/** Bottom 250px data-preview drawer with Debug Mode checkbox and dense table. */
|
|
4
4
|
export interface DataPreviewProps {
|
|
5
5
|
title?: string;
|
|
@@ -9,6 +9,8 @@ export interface DataPreviewProps {
|
|
|
9
9
|
onDebug?: (v: boolean) => void;
|
|
10
10
|
collapsed?: boolean;
|
|
11
11
|
onCollapse?: () => void;
|
|
12
|
+
/** Size tier of the drawer region. Defaults to "sm": 24px header controls, 32px table rows with 12px text. */
|
|
13
|
+
size?: "sm" | "md" | "lg";
|
|
12
14
|
style?: React.CSSProperties;
|
|
13
15
|
}
|
|
14
16
|
export declare function DataPreview(props: DataPreviewProps): JSX.Element;
|
|
@@ -2,21 +2,21 @@ import React from "react";
|
|
|
2
2
|
import { Icon } from "../icons/Icon.jsx";
|
|
3
3
|
import { IconButton } from "../buttons/IconButton.jsx";
|
|
4
4
|
import { Checkbox } from "../forms/Checkbox.jsx";
|
|
5
|
-
import {
|
|
5
|
+
import { Table } from "../data/Table.jsx";
|
|
6
6
|
|
|
7
|
-
/** Bottom data-preview drawer — 250px: 40px header (title, Debug Mode, collapse) + dense table. */
|
|
8
|
-
export function DataPreview({ title = "Data Preview", columns = [], rows = [], debug = false, onDebug, collapsed, onCollapse, style }) {
|
|
7
|
+
/** Bottom data-preview drawer — 250px: 40px header (title, Debug Mode, collapse) + dense table. An sm size region: the header's controls are 24px and the table has 32px rows with 12px text. */
|
|
8
|
+
export function DataPreview({ title = "Data Preview", columns = [], rows = [], debug = false, onDebug, collapsed, onCollapse, size = "sm", style }) {
|
|
9
9
|
return (
|
|
10
|
-
<div style={{ background: "var(--bg-surface)", borderTop: "1px solid var(--border-card)", display: "flex", flexDirection: "column", height: collapsed ?
|
|
11
|
-
<div style={{ height:
|
|
10
|
+
<div data-size={size} style={{ background: "var(--bg-surface)", borderTop: "1px solid var(--border-card)", display: "flex", flexDirection: "column", height: collapsed ? "var(--bar-card-h)" : "var(--drawer-h)", overflow: "hidden", boxSizing: "border-box", flexShrink: 0, transition: "height .15s ease", ...style }}>
|
|
11
|
+
<div style={{ height: "var(--bar-card-h)", display: "flex", alignItems: "center", gap: "var(--group-gap)", padding: "0 var(--edge-pad)", boxSizing: "border-box", flexShrink: 0 }}>
|
|
12
12
|
<span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-semibold)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", letterSpacing: "var(--tracking-base)", color: "var(--text-heading)" }}>{title}</span>
|
|
13
13
|
<span style={{ flex: 1 }} />
|
|
14
14
|
<Checkbox label="Debug Mode" checked={debug} onChange={onDebug} />
|
|
15
|
-
<IconButton icon={collapsed ? "chevron-up" : "chevron-down"}
|
|
15
|
+
<IconButton icon={collapsed ? "chevron-up" : "chevron-down"} muted onClick={onCollapse} label={collapsed ? "Expand" : "Collapse"} />
|
|
16
16
|
</div>
|
|
17
17
|
{!collapsed ? (
|
|
18
18
|
<div style={{ overflowY: "auto", borderTop: "1px solid var(--border-subtle)" }}>
|
|
19
|
-
<
|
|
19
|
+
<Table resizable columns={columns} rows={rows} headerBorder={false} />
|
|
20
20
|
</div>
|
|
21
21
|
) : null}
|
|
22
22
|
</div>
|
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
<script setup>
|
|
2
2
|
import IconButton from '../buttons/IconButton.vue'
|
|
3
3
|
import Checkbox from '../forms/Checkbox.vue'
|
|
4
|
-
import
|
|
5
|
-
// Bottom data-preview drawer — 250px: 40px header (title, Debug Mode, collapse) + dense table.
|
|
6
|
-
defineProps({ title: { type: String, default: 'Data Preview' }, columns: { type: Array, default: () => [] }, rows: { type: Array, default: () => [] }, debug: Boolean, collapsed: Boolean, style: Object })
|
|
4
|
+
import Table from '../data/Table.vue'
|
|
5
|
+
// Bottom data-preview drawer — 250px: 40px header (title, Debug Mode, collapse) + dense table. An sm size region: the header's controls are 24px and the table has 32px rows with 12px text.
|
|
6
|
+
defineProps({ title: { type: String, default: 'Data Preview' }, columns: { type: Array, default: () => [] }, rows: { type: Array, default: () => [] }, debug: Boolean, collapsed: Boolean, size: { type: String, default: 'sm' }, style: Object })
|
|
7
7
|
const emit = defineEmits(['update:debug', 'toggleCollapse'])
|
|
8
8
|
</script>
|
|
9
9
|
<template>
|
|
10
|
-
<div :style="{ background: 'var(--bg-surface)', borderTop: '1px solid var(--border-card)', display: 'flex', flexDirection: 'column', height: collapsed ?
|
|
11
|
-
<div style="height:
|
|
10
|
+
<div :data-size="size" :style="{ background: 'var(--bg-surface)', borderTop: '1px solid var(--border-card)', display: 'flex', flexDirection: 'column', height: collapsed ? 'var(--bar-card-h)' : 'var(--drawer-h)', overflow: 'hidden', boxSizing: 'border-box', flexShrink: 0, transition: 'height .15s ease', ...style }">
|
|
11
|
+
<div style="height:var(--bar-card-h);display:flex;align-items:center;gap:var(--group-gap);padding:0 var(--edge-pad);box-sizing:border-box;flex-shrink:0">
|
|
12
12
|
<span style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-heading)">{{ title }}</span>
|
|
13
13
|
<span style="flex:1" />
|
|
14
14
|
<Checkbox label="Debug Mode" :checked="debug" @change="v => emit('update:debug', v)" />
|
|
15
|
-
<IconButton :icon="collapsed ? 'chevron-up' : 'chevron-down'"
|
|
15
|
+
<IconButton :icon="collapsed ? 'chevron-up' : 'chevron-down'" muted :label="collapsed ? 'Expand' : 'Collapse'" @click="emit('toggleCollapse')" />
|
|
16
16
|
</div>
|
|
17
17
|
<div v-if="!collapsed" style="overflow-y:auto;border-top:1px solid var(--border-subtle)">
|
|
18
|
-
<
|
|
18
|
+
<Table resizable :columns="columns" :rows="rows" :header-border="false" />
|
|
19
19
|
</div>
|
|
20
20
|
</div>
|
|
21
21
|
</template>
|
|
@@ -60,12 +60,12 @@ export function NodeCard({ title, subtitle, icon = "table", subtitleIcon, hue =
|
|
|
60
60
|
{badge === "clock" ? <StatusBadge tone="pending" icon="clock" size={20} style={{ position: "absolute", top: -6, right: -6 }} /> : null}
|
|
61
61
|
</span>
|
|
62
62
|
<div style={{ display: "flex", flexDirection: "column", minWidth: 0, flex: 1, paddingRight: 18 }}>
|
|
63
|
-
<span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-semibold)", fontSize: "var(--text-base)", lineHeight: "
|
|
63
|
+
<span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-semibold)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", letterSpacing: "var(--tracking-base)", color: "var(--text-heading)", whiteSpace: "nowrap", overflow: "hidden", textOverflow: "ellipsis" }}>{title}</span>
|
|
64
64
|
<span style={{ display: "flex", alignItems: "flex-start", gap: 4, paddingTop: 4, minWidth: 0 }}>
|
|
65
|
-
{subtitleIcon !== false ? <span style={{ color: "var(--text-muted)", display: "inline-flex", flexShrink: 0,
|
|
65
|
+
{subtitleIcon !== false ? <span style={{ color: "var(--text-muted)", display: "inline-flex", alignItems: "center", flexShrink: 0, height: "var(--leading-xs)", transform: "translateY(-0.5px)" }}><Icon name={subtitleIcon || "info"} size={12} /></span> : null}
|
|
66
66
|
{/* Node types run long ("Field Value Calculation"), so the subtitle wraps to a
|
|
67
67
|
second line and only then clamps — the card size never changes. */}
|
|
68
|
-
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", lineHeight: "
|
|
68
|
+
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", lineHeight: "var(--leading-xs)", letterSpacing: "var(--tracking-xs)", color: "var(--text-muted)", minWidth: 0, overflow: "hidden", display: "-webkit-box", WebkitBoxOrient: "vertical", WebkitLineClamp: 2, overflowWrap: "break-word" }}>{subtitle}</span>
|
|
69
69
|
</span>
|
|
70
70
|
</div>
|
|
71
71
|
</div>
|
|
@@ -38,11 +38,11 @@ const tone = i => props.inputTones[i] || 'default'
|
|
|
38
38
|
<StatusBadge v-if="badge === 'clock'" tone="pending" icon="clock" :size="20" style="position:absolute;top:-6px;right:-6px" />
|
|
39
39
|
</span>
|
|
40
40
|
<div style="display:flex;flex-direction:column;min-width:0;flex:1;padding-right:18px">
|
|
41
|
-
<span style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-base);line-height:
|
|
41
|
+
<span style="font-family:var(--font-sans);font-weight:var(--weight-semibold);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-heading);white-space:nowrap;overflow:hidden;text-overflow:ellipsis">{{ title }}</span>
|
|
42
42
|
<span style="display:flex;align-items:flex-start;gap:4px;padding-top:4px;min-width:0">
|
|
43
|
-
<span v-if="subtitleIcon !== false" style="color:var(--text-muted);display:inline-flex;flex-shrink:0;
|
|
43
|
+
<span v-if="subtitleIcon !== false" style="color:var(--text-muted);display:inline-flex;align-items:center;flex-shrink:0;height:var(--leading-xs);transform:translateY(-0.5px)"><Icon :name="subtitleIcon || 'info'" :size="12" /></span>
|
|
44
44
|
<!-- Node types run long ("Field Value Calculation"): wrap to a second line, then clamp. -->
|
|
45
|
-
<span style="font-family:var(--font-sans);font-size:var(--text-xs);line-height:
|
|
45
|
+
<span style="font-family:var(--font-sans);font-size:var(--text-xs);line-height:var(--leading-xs);letter-spacing:var(--tracking-xs);color:var(--text-muted);min-width:0;overflow:hidden;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:2;overflow-wrap:break-word">{{ subtitle }}</span>
|
|
46
46
|
</span>
|
|
47
47
|
</div>
|
|
48
48
|
</div>
|
|
@@ -8,8 +8,8 @@ const hover = ref(false)
|
|
|
8
8
|
</script>
|
|
9
9
|
<template>
|
|
10
10
|
<div role="button" tabindex="0" @click="$emit('click')" @mouseenter="hover = true" @mouseleave="hover = false"
|
|
11
|
-
:style="{ width: 67.
|
|
11
|
+
:style="{ width: '67.664px', borderRadius: 'var(--radius-lg)', padding: '8px', display: 'flex', flexDirection: 'column', gap: '6px', alignItems: 'center', cursor: 'grab', boxSizing: 'border-box', background: hover ? 'var(--bg-hover)' : 'transparent', transition: 'background .12s ease', ...style }">
|
|
12
12
|
<IconTile :icon="icon" :hue="hue" kind="palette" />
|
|
13
|
-
<span style="font-family:var(--font-sans);font-size:var(--text-
|
|
13
|
+
<span style="font-family:var(--font-sans);font-size:var(--text-xs);line-height:var(--leading-xs);letter-spacing:var(--tracking-xs);color:var(--text-body);text-align:center">{{ label }}</span>
|
|
14
14
|
</div>
|
|
15
15
|
</template>
|
|
@@ -8,7 +8,7 @@ const hover = ref(false)
|
|
|
8
8
|
</script>
|
|
9
9
|
<template>
|
|
10
10
|
<div role="button" tabindex="0" @click="$emit('click')" @mouseenter="hover = true" @mouseleave="hover = false"
|
|
11
|
-
:style="{ height: 'var(--h-subnav-item)', borderRadius: 'var(--radius-md)', display: 'flex', alignItems: 'center', gap:
|
|
11
|
+
:style="{ height: 'var(--h-subnav-item)', borderRadius: 'var(--radius-md)', display: 'flex', alignItems: 'center', gap: '8px', padding: '6px 8px', boxSizing: 'border-box', cursor: 'grab', background: hover ? 'var(--bg-hover)' : 'transparent', ...style }">
|
|
12
12
|
<span :style="{ color: `var(--cat-${hue})`, display: 'inline-flex' }"><Icon :name="icon" :size="14" /></span>
|
|
13
13
|
<span style="font-family:var(--font-sans);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-body);white-space:nowrap">{{ label }}</span>
|
|
14
14
|
</div>
|
|
@@ -11,7 +11,7 @@ export function PaletteItem({ icon, hue, label, onClick, style }) {
|
|
|
11
11
|
<div role="button" tabIndex={0} onClick={onClick} onMouseEnter={() => setHover(true)} onMouseLeave={() => setHover(false)}
|
|
12
12
|
style={{ width: 67.664, borderRadius: "var(--radius-lg)", padding: 8, display: "flex", flexDirection: "column", gap: 6, alignItems: "center", cursor: "grab", boxSizing: "border-box", background: hover ? "var(--bg-hover)" : "transparent", transition: "background .12s ease", ...style }}>
|
|
13
13
|
<IconTile icon={icon} hue={hue} kind="palette" />
|
|
14
|
-
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-
|
|
14
|
+
<span style={{ fontFamily: "var(--font-sans)", fontSize: "var(--text-xs)", lineHeight: "var(--leading-xs)", letterSpacing: "var(--tracking-xs)", color: "var(--text-body)", textAlign: "center" }}>{label}</span>
|
|
15
15
|
</div>
|
|
16
16
|
);
|
|
17
17
|
}
|
|
@@ -44,7 +44,7 @@ export function PalettePanel({ catalog = PIPELINE_CATALOG, height = "100%", onPi
|
|
|
44
44
|
<div style={{ flex: 1, overflowY: "auto", padding: 8 }}>
|
|
45
45
|
{catalog.map((cat) => (
|
|
46
46
|
<div key={cat.label}>
|
|
47
|
-
<div onClick={() => toggle(cat.label)} style={{ height: "var(--h-subnav-item)", borderRadius: "var(--radius-md)", display: "flex", alignItems: "center", gap: 8, padding: "6px 8px", boxSizing: "border-box", cursor: "pointer" }}>
|
|
47
|
+
<div onClick={() => toggle(cat.label)} data-wash="" style={{ height: "var(--h-subnav-item)", borderRadius: "var(--radius-md)", display: "flex", alignItems: "center", gap: 8, padding: "6px 8px", boxSizing: "border-box", cursor: "pointer", background: "var(--wash, transparent)", transition: "var(--t-hover)" }}>
|
|
48
48
|
<span style={{ color: "var(--text-muted)", display: "inline-flex", transform: closed.includes(cat.label) ? "rotate(-90deg)" : "none", transition: "transform .15s ease" }}><Icon name="chevron-down" size={14} /></span>
|
|
49
49
|
<span style={{ color: `var(--cat-${cat.hue})`, display: "inline-flex" }}><Icon name={cat.icon} size={14} /></span>
|
|
50
50
|
<span style={{ fontFamily: "var(--font-sans)", fontWeight: "var(--weight-medium)", fontSize: "var(--text-base)", lineHeight: "var(--leading-base)", letterSpacing: "var(--tracking-base)", color: "var(--text-strong)" }}>{cat.label}</span>
|
|
@@ -21,7 +21,7 @@ function toggle(l) { closed.value = closed.value.includes(l) ? closed.value.filt
|
|
|
21
21
|
</div>
|
|
22
22
|
<div style="flex:1;overflow-y:auto;padding:8px">
|
|
23
23
|
<div v-for="cat in catalog" :key="cat.label">
|
|
24
|
-
<div @click="toggle(cat.label)" style="height:var(--h-subnav-item);border-radius:var(--radius-md);display:flex;align-items:center;gap:8px;padding:6px 8px;box-sizing:border-box;cursor:pointer">
|
|
24
|
+
<div @click="toggle(cat.label)" data-wash="" style="height:var(--h-subnav-item);border-radius:var(--radius-md);display:flex;align-items:center;gap:8px;padding:6px 8px;box-sizing:border-box;cursor:pointer;background:var(--wash, transparent);transition:var(--t-hover)">
|
|
25
25
|
<span :style="{ color: 'var(--text-muted)', display: 'inline-flex', transform: closed.includes(cat.label) ? 'rotate(-90deg)' : 'none', transition: 'transform .15s ease' }"><Icon name="chevron-down" :size="14" /></span>
|
|
26
26
|
<span :style="{ color: `var(--cat-${cat.hue})`, display: 'inline-flex' }"><Icon :name="cat.icon" :size="14" /></span>
|
|
27
27
|
<span style="font-family:var(--font-sans);font-weight:var(--weight-medium);font-size:var(--text-base);line-height:var(--leading-base);letter-spacing:var(--tracking-base);color:var(--text-strong)">{{ cat.label }}</span>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
<script setup>
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import Icon from '../icons/Icon.vue'
|
|
4
|
+
import { portSkin } from './port-skin.js'
|
|
5
|
+
// Round output/input port — 22px. tone: "default" | "active" (dragging from it) | "target" (drop here).
|
|
6
|
+
// interactive lights it on hover and shows a grab cursor. Native listeners (@mousedown, @mouseup…) fall through to the span.
|
|
7
|
+
defineProps({ tone: { type: String, default: 'default' }, interactive: Boolean, style: Object })
|
|
8
|
+
const hover = ref(false)
|
|
9
|
+
</script>
|
|
10
|
+
<template>
|
|
11
|
+
<span @mouseenter="hover = true" @mouseleave="hover = false"
|
|
12
|
+
:style="{ width: '22px', height: '22px', borderRadius: 'var(--radius-full)', boxSizing: 'border-box', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', ...portSkin(tone, hover, interactive), ...style }">
|
|
13
|
+
<Icon :name="tone === 'target' ? 'plus' : 'arrow-right'" :size="12" :stroke-width="2.2" />
|
|
14
|
+
</span>
|
|
15
|
+
</template>
|