@keyfunc/keybricks-ds 1.0.4 → 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 +174 -35
- package/SKILL.md +6 -4
- package/_adherence.oxlintrc.json +164 -68
- 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 +2 -2
- package/components/_cards/search.card.html +5 -2
- package/components/_cards/segmented-control.card.html +2 -2
- 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 +3 -3
- 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/_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 +5 -3
- package/components/forms/Radio.jsx +13 -15
- package/components/forms/Radio.vue +9 -10
- package/components/forms/RadioGroup.vue +5 -5
- 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 +2 -2
- package/components/forms/Switch.jsx +20 -22
- package/components/forms/Switch.vue +15 -14
- package/components/forms/Textarea.vue +4 -4
- package/components/forms/forms.prompt.md +1 -1
- package/components/forms/input-base.js +2 -1
- package/components/index.d.ts +1 -2
- package/components/index.js +3 -4
- 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 +2 -2
- package/components/tabs/SegmentedControl.jsx +7 -7
- package/components/tabs/SegmentedControl.vue +7 -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 +1 -1
- package/keybricks.css +4 -0
- package/package.json +6 -3
- package/readme.md +90 -122
- 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
|
@@ -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>
|
|
@@ -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
|
+
// Labeled input port pill ("A >", "B >") — 28×22, same three tones as Port.
|
|
6
|
+
defineProps({ label: { type: String, default: 'A' }, tone: { type: String, default: 'default' }, interactive: Boolean, style: Object })
|
|
7
|
+
const hover = ref(false)
|
|
8
|
+
</script>
|
|
9
|
+
<template>
|
|
10
|
+
<span @mouseenter="hover = true" @mouseleave="hover = false"
|
|
11
|
+
:style="{ width: '28px', height: '22px', borderRadius: 'var(--radius-full)', boxSizing: 'border-box', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: '2px', fontFamily: 'var(--font-sans)', fontSize: 'var(--text-xs)', letterSpacing: 'var(--tracking-xs)', lineHeight: 1, ...portSkin(tone, hover, interactive), ...style }">
|
|
12
|
+
<Icon v-if="tone === 'target'" name="plus" :size="12" :stroke-width="2.2" />
|
|
13
|
+
<template v-else>{{ label }}<Icon name="chevron-right" :size="9" :stroke-width="2.5" /></template>
|
|
14
|
+
</span>
|
|
15
|
+
</template>
|
|
@@ -5,7 +5,7 @@ const props = defineProps({ modelValue: { type: Number, default: 100 }, style: O
|
|
|
5
5
|
const emit = defineEmits(['update:modelValue', 'fit'])
|
|
6
6
|
</script>
|
|
7
7
|
<template>
|
|
8
|
-
<div :style="{ display: 'inline-flex', alignItems: 'center', gap:
|
|
8
|
+
<div :style="{ display: 'inline-flex', alignItems: 'center', gap: '2px', background: 'var(--bg-surface)', border: '1px solid var(--border-control)', borderRadius: 'var(--radius-md)', boxShadow: 'var(--shadow-menu)', padding: '3px', boxSizing: 'border-box', ...style }">
|
|
9
9
|
<IconButton icon="minus" size="sm" label="Zoom out" @click="emit('update:modelValue', Math.max(25, modelValue - 10))" />
|
|
10
10
|
<span style="min-width:40px;text-align:center;font-family:var(--font-sans);font-size:var(--text-xs);color:var(--text-secondary)">{{ modelValue }}%</span>
|
|
11
11
|
<IconButton icon="plus" size="sm" label="Zoom in" @click="emit('update:modelValue', Math.min(200, modelValue + 10))" />
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Shared port skin for Port.vue / PortLabel.vue / NodeCard.vue — mirrors portSkin() in NodeCard.jsx.
|
|
2
|
+
// tone: "default" | "active" (a wire is being dragged from it) | "target" (valid drop here).
|
|
3
|
+
export function portSkin(tone, hover, interactive) {
|
|
4
|
+
const hot = tone === 'active' || tone === 'target' || (interactive && hover)
|
|
5
|
+
return {
|
|
6
|
+
background: tone === 'target' ? 'var(--soft-bg)' : 'var(--bg-surface)',
|
|
7
|
+
border: `2px solid ${hot ? 'var(--action-primary)' : 'var(--port-border)'}`,
|
|
8
|
+
boxShadow: tone === 'active' || tone === 'target' ? '0 0 0 3px var(--focus-ring)' : 'none',
|
|
9
|
+
color: hot ? 'var(--action-primary)' : 'var(--text-muted)',
|
|
10
|
+
cursor: interactive ? (tone === 'active' ? 'grabbing' : 'grab') : 'default',
|
|
11
|
+
transition: 'var(--t-hover)'
|
|
12
|
+
}
|
|
13
|
+
}
|
package/components/px.js
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
// Vue's :style binding does not append "px" to numbers the way React does —
|
|
2
|
+
// { height: 30 } is silently dropped by the browser. Wrap any numeric length in px().
|
|
3
|
+
// Strings ('100%', 'var(--radius-md)', '12px') pass through untouched.
|
|
4
|
+
export const px = (v) => (typeof v === 'number' ? v + 'px' : v)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
2
|
+
// Panel tabs (Node Info · Calc Rules · …): a lighter underline tab bar at the region's bar height with regular-weight control text. Put the panel in an sm region for the compact 32px/12px look.
|
|
3
|
+
defineProps({ tabs: { type: Array, default: () => [] }, active: String, size: String, style: Object })
|
|
3
4
|
const emit = defineEmits(['change'])
|
|
4
5
|
</script>
|
|
5
6
|
<template>
|
|
6
|
-
<div :style="{ display: 'flex', borderBottom: '1px solid var(--border-subtle)', ...style }">
|
|
7
|
-
<button v-for="t in tabs" :key="t" type="button" @click="emit('change', t)"
|
|
8
|
-
:style="{ background: 'transparent', border: 'none', cursor: 'pointer', padding: '
|
|
7
|
+
<div role="tablist" :data-size="size" :style="{ display: 'flex', borderBottom: '1px solid var(--border-subtle)', ...style }">
|
|
8
|
+
<button v-for="t in tabs" :key="t" type="button" role="tab" :aria-selected="t === active" :data-ink="t === active ? undefined : ''" @click="emit('change', t)"
|
|
9
|
+
:style="{ background: 'transparent', border: 'none', cursor: 'pointer', height: 'var(--bar-h)', boxSizing: 'border-box', padding: '0 var(--control-px)', marginBottom: '-1px', borderBottom: t === active ? '2px solid var(--action-primary)' : '2px solid transparent', fontFamily: 'var(--font-sans)', fontSize: 'var(--control-text)', lineHeight: 'var(--control-leading)', letterSpacing: 'var(--control-tracking)', color: t === active ? 'var(--action-primary)' : 'var(--ink, var(--text-secondary))', whiteSpace: 'nowrap' }">{{ t }}</button>
|
|
9
10
|
</div>
|
|
10
11
|
</template>
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
<script setup>
|
|
2
|
-
|
|
2
|
+
// Text pill filter tabs. Active = tinted pill. Pills are control-height (sm 24 · md 32 · lg 36); omit `size` to inherit.
|
|
3
|
+
defineProps({ tabs: { type: Array, default: () => [] }, active: String, size: String, style: Object })
|
|
3
4
|
const emit = defineEmits(['change'])
|
|
4
5
|
</script>
|
|
5
6
|
<template>
|
|
6
|
-
<div :style="{ display: 'flex', gap:
|
|
7
|
-
<button v-for="t in tabs" :key="t" type="button" @click="emit('change', t)"
|
|
8
|
-
:style="{ background: t === active ? 'var(--bg-active)' : 'transparent', border: 'none', cursor: 'pointer', height:
|
|
7
|
+
<div role="tablist" :data-size="size" :style="{ display: 'flex', gap: 'var(--control-gap)', ...style }">
|
|
8
|
+
<button v-for="t in tabs" :key="t" type="button" role="tab" :aria-selected="t === active" :data-ink="t === active ? undefined : ''" :data-wash="t === active ? undefined : ''" @click="emit('change', t)"
|
|
9
|
+
:style="{ background: t === active ? 'var(--bg-active)' : 'var(--wash, transparent)', border: 'none', cursor: 'pointer', height: 'var(--control-h)', padding: '0 var(--control-px)', borderRadius: 'var(--radius-md)', fontFamily: 'var(--font-sans)', fontWeight: 'var(--weight-medium)', fontSize: 'var(--control-text)', lineHeight: 'var(--control-leading)', letterSpacing: 'var(--control-tracking)', color: t === active ? 'var(--text-heading)' : 'var(--ink, var(--text-secondary))', whiteSpace: 'nowrap' }">{{ t }}</button>
|
|
9
10
|
</div>
|
|
10
11
|
</template>
|
|
@@ -5,8 +5,8 @@ export interface SegmentedControlProps {
|
|
|
5
5
|
options?: (string | { label: string; icon?: string; disabled?: boolean })[];
|
|
6
6
|
value?: string;
|
|
7
7
|
onChange?: (value: string) => void;
|
|
8
|
-
/** md
|
|
9
|
-
size?: "sm" | "md";
|
|
8
|
+
/** Size tier: sm 24 · md 32 · lg 36. Omit to inherit the enclosing region's tier (the default). */
|
|
9
|
+
size?: "sm" | "md" | "lg";
|
|
10
10
|
/** Hide labels; each label becomes the segment's aria-label and tooltip */
|
|
11
11
|
iconOnly?: boolean;
|
|
12
12
|
/** Greys the whole control */
|
|
@@ -4,12 +4,12 @@ import { Icon } from "../icons/Icon.jsx";
|
|
|
4
4
|
/**
|
|
5
5
|
* Segmented control — inset track, raised active segment. Switches views of the same data, applies instantly.
|
|
6
6
|
* options: string[] | { label, icon?, disabled? }[] value/onChange by label
|
|
7
|
-
* size
|
|
7
|
+
* size sm 24 | md 32 | lg 36 — omit it to inherit the region's tier · iconOnly hides labels (label becomes aria-label / title)
|
|
8
8
|
* disabled greys the whole control · fullWidth stretches segments evenly
|
|
9
9
|
* Keyboard: ← → move between enabled segments.
|
|
10
10
|
*/
|
|
11
|
-
|
|
12
|
-
|
|
11
|
+
const tierIcon = { width: "var(--control-icon)", height: "var(--control-icon)" };
|
|
12
|
+
export function SegmentedControl({ options = [], value, onChange, size, iconOnly, disabled, fullWidth, style }) {
|
|
13
13
|
const opts = options.map((o) => (typeof o === "string" ? { label: o } : o));
|
|
14
14
|
const enabled = opts.filter((o) => !o.disabled);
|
|
15
15
|
const onKey = (e) => {
|
|
@@ -20,14 +20,14 @@ export function SegmentedControl({ options = [], value, onChange, size = "md", i
|
|
|
20
20
|
onChange && onChange(n.label);
|
|
21
21
|
};
|
|
22
22
|
return (
|
|
23
|
-
<div role="tablist" aria-disabled={disabled || undefined} onKeyDown={onKey} style={{ display: fullWidth ? "flex" : "inline-flex", padding: 2, gap: 2, background: "var(--bg-inset)", border: "1px solid var(--border-control)", borderRadius: "var(--radius-md)", boxSizing: "border-box", opacity: disabled ? .5 : 1, ...style }}>
|
|
23
|
+
<div role="tablist" data-size={size} aria-disabled={disabled || undefined} onKeyDown={onKey} style={{ display: fullWidth ? "flex" : "inline-flex", height: "var(--control-h)", padding: 2, gap: 2, background: "var(--bg-inset)", border: "1px solid var(--border-control)", borderRadius: "var(--radius-md)", boxSizing: "border-box", opacity: disabled ? .5 : 1, ...style }}>
|
|
24
24
|
{opts.map((o) => {
|
|
25
25
|
const is = value === o.label, off = disabled || o.disabled;
|
|
26
26
|
return (
|
|
27
|
-
<button key={o.label} type="button" role="tab" aria-selected={is} aria-label={iconOnly ? o.label : undefined} title={iconOnly ? o.label : undefined} disabled={off} tabIndex={is ? 0 : -1}
|
|
27
|
+
<button key={o.label} type="button" role="tab" aria-selected={is} aria-label={iconOnly ? o.label : undefined} title={iconOnly ? o.label : undefined} disabled={off} tabIndex={is ? 0 : -1} data-ink={is || off ? undefined : ""}
|
|
28
28
|
onClick={() => !off && onChange && onChange(o.label)}
|
|
29
|
-
style={{ height: h -
|
|
30
|
-
{o.icon ? <Icon name={o.icon} size={
|
|
29
|
+
style={{ height: "calc(var(--control-h) - 6px)", padding: iconOnly ? "0 calc(var(--control-px) - 4px)" : "0 calc(var(--control-px) - 2px)", flex: fullWidth ? 1 : "none", justifyContent: "center", display: "inline-flex", alignItems: "center", gap: 6, borderRadius: "var(--radius-sm)", border: "none", cursor: off ? "not-allowed" : "pointer", background: is ? "var(--bg-surface)" : "transparent", boxShadow: is ? "0 1px 2px rgba(0,0,0,.08)" : "none", fontFamily: "var(--font-sans)", fontWeight: "var(--weight-medium)", fontSize: "var(--control-text)", lineHeight: "var(--control-leading)", letterSpacing: "var(--control-tracking)", color: is ? "var(--text-heading)" : "var(--ink, var(--text-secondary))", opacity: o.disabled && !disabled ? .45 : 1, whiteSpace: "nowrap", transition: "var(--t-hover)" }}>
|
|
30
|
+
{o.icon ? <Icon name={o.icon} size={16} style={tierIcon} /> : null}{iconOnly ? null : o.label}
|
|
31
31
|
</button>
|
|
32
32
|
);
|
|
33
33
|
})}
|
|
@@ -2,13 +2,13 @@
|
|
|
2
2
|
import { computed } from 'vue'
|
|
3
3
|
import Icon from '../icons/Icon.vue'
|
|
4
4
|
// Segmented control — inset track, raised active segment. Switches views of the same data, applies instantly.
|
|
5
|
-
// options: string[] | { label, icon?, disabled? }[] · v-model by label · size md
|
|
5
|
+
// options: string[] | { label, icon?, disabled? }[] · v-model by label · size sm 24 | md 32 | lg 36 — omit it to inherit the region's tier
|
|
6
6
|
// iconOnly hides labels (label → aria-label/title) · disabled greys the control · fullWidth stretches segments · ← → keyboard.
|
|
7
|
-
const
|
|
7
|
+
const tierIcon = { width: 'var(--control-icon)', height: 'var(--control-icon)' }
|
|
8
|
+
const props = defineProps({ options: { type: Array, default: () => [] }, modelValue: String, size: String, iconOnly: Boolean, disabled: Boolean, fullWidth: Boolean, style: Object })
|
|
8
9
|
const emit = defineEmits(['update:modelValue'])
|
|
9
10
|
const opts = computed(() => props.options.map(o => typeof o === 'string' ? { label: o } : o))
|
|
10
11
|
const enabled = computed(() => opts.value.filter(o => !o.disabled))
|
|
11
|
-
const h = computed(() => props.size === 'sm' ? 26 : 32)
|
|
12
12
|
const pick = (o) => { if (!(props.disabled || o.disabled)) emit('update:modelValue', o.label) }
|
|
13
13
|
function onKey(e) {
|
|
14
14
|
if ((e.key !== 'ArrowLeft' && e.key !== 'ArrowRight') || props.disabled || !enabled.value.length) return
|
|
@@ -18,10 +18,10 @@ function onKey(e) {
|
|
|
18
18
|
}
|
|
19
19
|
</script>
|
|
20
20
|
<template>
|
|
21
|
-
<div role="tablist" :aria-disabled="disabled || undefined" @keydown="onKey" :style="{ display: fullWidth ? 'flex' : 'inline-flex', padding: '2px', gap: '2px', background: 'var(--bg-inset)', border: '1px solid var(--border-control)', borderRadius: 'var(--radius-md)', boxSizing: 'border-box', opacity: disabled ? .5 : 1, ...style }">
|
|
22
|
-
<button v-for="o in opts" :key="o.label" type="button" role="tab" :aria-selected="modelValue === o.label" :aria-label="iconOnly ? o.label : undefined" :title="iconOnly ? o.label : undefined" :disabled="disabled || o.disabled" :tabindex="modelValue === o.label ? 0 : -1" @click="pick(o)"
|
|
23
|
-
:style="{ height: (h -
|
|
24
|
-
<Icon v-if="o.icon" :name="o.icon" :size="
|
|
21
|
+
<div role="tablist" :data-size="size" :aria-disabled="disabled || undefined" @keydown="onKey" :style="{ display: fullWidth ? 'flex' : 'inline-flex', height: 'var(--control-h)', padding: '2px', gap: '2px', background: 'var(--bg-inset)', border: '1px solid var(--border-control)', borderRadius: 'var(--radius-md)', boxSizing: 'border-box', opacity: disabled ? .5 : 1, ...style }">
|
|
22
|
+
<button v-for="o in opts" :key="o.label" type="button" role="tab" :aria-selected="modelValue === o.label" :aria-label="iconOnly ? o.label : undefined" :title="iconOnly ? o.label : undefined" :disabled="disabled || o.disabled" :tabindex="modelValue === o.label ? 0 : -1" :data-ink="modelValue === o.label || disabled || o.disabled ? undefined : ''" @click="pick(o)"
|
|
23
|
+
:style="{ height: 'calc(var(--control-h) - 6px)', padding: iconOnly ? '0 calc(var(--control-px) - 4px)' : '0 calc(var(--control-px) - 2px)', flex: fullWidth ? 1 : 'none', justifyContent: 'center', display: 'inline-flex', alignItems: 'center', gap: '6px', borderRadius: 'var(--radius-sm)', border: 'none', cursor: (disabled || o.disabled) ? 'not-allowed' : 'pointer', background: modelValue === o.label ? 'var(--bg-surface)' : 'transparent', boxShadow: modelValue === o.label ? '0 1px 2px rgba(0,0,0,.08)' : 'none', fontFamily: 'var(--font-sans)', fontWeight: 'var(--weight-medium)', fontSize: 'var(--control-text)', lineHeight: 'var(--control-leading)', letterSpacing: 'var(--control-tracking)', color: modelValue === o.label ? 'var(--text-heading)' : 'var(--ink, var(--text-secondary))', opacity: o.disabled && !disabled ? .45 : 1, whiteSpace: 'nowrap', transition: 'var(--t-hover)' }">
|
|
24
|
+
<Icon v-if="o.icon" :name="o.icon" :size="16" :style="tierIcon" /><template v-if="!iconOnly">{{ o.label }}</template>
|
|
25
25
|
</button>
|
|
26
26
|
</div>
|
|
27
27
|
</template>
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
import * as React from "react";
|
|
2
|
-
/** Underline tabs (Import/Export). Active: blue text + 2px blue underline on hairline baseline. */
|
|
2
|
+
/** Underline tabs (Import/Export). Active: blue text + 2px blue underline on hairline baseline. The bar is the region's bar height (sm 32 · md 40 · lg 44). */
|
|
3
3
|
export interface TabsProps {
|
|
4
4
|
tabs?: string[];
|
|
5
5
|
active?: string;
|
|
6
6
|
onChange?: (tab: string) => void;
|
|
7
|
+
/** Size tier. Omit to inherit the enclosing region's tier (the default). */
|
|
8
|
+
size?: "sm" | "md" | "lg";
|
|
7
9
|
style?: React.CSSProperties;
|
|
8
10
|
}
|
|
9
11
|
export declare function Tabs(props: TabsProps): JSX.Element;
|
|
10
|
-
/**
|
|
12
|
+
/** Lighter underline tabs for panels (Node Info / Calc Rules / ...), regular weight; an sm region gives the compact 32px/12px look. */
|
|
11
13
|
export declare function PanelTabs(props: TabsProps): JSX.Element;
|
|
12
|
-
/** Text pill filter tabs; active gets a
|
|
14
|
+
/** Text pill filter tabs at control height; active gets a tinted pill. */
|
|
13
15
|
export declare function PillTabs(props: TabsProps): JSX.Element;
|