@selvajs/ui 6.3.0 → 6.3.2
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/dist/components/preview/TabContent.svelte +18 -16
- package/dist/components/viewer/SceneManager.svelte +3 -1
- package/dist/schema/visibility-rules.d.ts +6 -0
- package/dist/schema/visibility-rules.js +9 -0
- package/package.json +13 -13
- package/src/lib/components/preview/TabContent.svelte +18 -16
- package/src/lib/components/viewer/SceneManager.svelte +3 -1
- package/src/lib/schema/visibility-rules.ts +12 -1
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
dynamicOptions = {}
|
|
43
43
|
}: Props = $props();
|
|
44
44
|
|
|
45
|
+
const visibleGroups = $derived(
|
|
46
|
+
tab.groups.filter((group) => evaluateGroupVisibility(group, values))
|
|
47
|
+
);
|
|
48
|
+
|
|
45
49
|
function getInputById(paramId: string): SchemaInput | undefined {
|
|
46
50
|
return inputs.find((i) => i.id === paramId);
|
|
47
51
|
}
|
|
@@ -82,25 +86,23 @@
|
|
|
82
86
|
<Tabs.Content value={tab.id} class="min-h-0 p-0 flex-1">
|
|
83
87
|
<ScrollArea class="h-full" orientation="vertical">
|
|
84
88
|
<div class="p-4 tab-content-container">
|
|
85
|
-
{#if
|
|
89
|
+
{#if visibleGroups.length === 0}
|
|
86
90
|
<StateDisplay type="empty" size="medium" message={t.tabNoGroups} />
|
|
87
91
|
{:else}
|
|
88
92
|
<div class="gap-8 flex flex-col">
|
|
89
|
-
{#each
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
/>
|
|
103
|
-
{/if}
|
|
93
|
+
{#each visibleGroups as group (group.id)}
|
|
94
|
+
<Group
|
|
95
|
+
label={group.label}
|
|
96
|
+
description={group.description}
|
|
97
|
+
items={group.items}
|
|
98
|
+
columns={group.columns ?? 1}
|
|
99
|
+
collapsed={collapsedGroups[group.id] ?? false}
|
|
100
|
+
{values}
|
|
101
|
+
onToggle={() => onToggleGroup(group.id)}
|
|
102
|
+
inputSnippet={renderInput}
|
|
103
|
+
outputSnippet={renderOutput}
|
|
104
|
+
flat={visibleGroups.length === 1}
|
|
105
|
+
/>
|
|
104
106
|
{/each}
|
|
105
107
|
</div>
|
|
106
108
|
{/if}
|
|
@@ -134,6 +134,8 @@
|
|
|
134
134
|
for (const [layerName, entries] of layerGroups) {
|
|
135
135
|
flat.push({
|
|
136
136
|
kind: 'layer',
|
|
137
|
+
// Prefixed, like the object rows below: a layer row must never share a key with
|
|
138
|
+
// an object row whose identity happens to read like a layer name.
|
|
137
139
|
key: `layer:${layerName}`,
|
|
138
140
|
top,
|
|
139
141
|
height: LAYER_ROW_HEIGHT,
|
|
@@ -145,7 +147,7 @@
|
|
|
145
147
|
for (const entry of entries) {
|
|
146
148
|
flat.push({
|
|
147
149
|
kind: 'object',
|
|
148
|
-
key: entry.
|
|
150
|
+
key: `obj:${entry.rowKey}`,
|
|
149
151
|
top,
|
|
150
152
|
height: OBJECT_ROW_HEIGHT,
|
|
151
153
|
entry
|
|
@@ -17,4 +17,10 @@ export declare function itemKey(item: LayoutItem): string;
|
|
|
17
17
|
export declare function buildVisibilityMap(items: LayoutItem[], values: Record<string, unknown>): Record<string, VisibilityResult>;
|
|
18
18
|
export declare function evaluateGroupVisibility(group: {
|
|
19
19
|
visibilityCondition?: GroupVisibilityCondition;
|
|
20
|
+
items?: LayoutItem[];
|
|
20
21
|
}, values: Record<string, unknown>): boolean;
|
|
22
|
+
/**
|
|
23
|
+
* A linebreak is always "visible" but renders as a divider only, so a group left with
|
|
24
|
+
* nothing but separators counts as empty.
|
|
25
|
+
*/
|
|
26
|
+
export declare function hasVisibleItems(items: LayoutItem[], values: Record<string, unknown>): boolean;
|
|
@@ -74,9 +74,18 @@ export function buildVisibilityMap(items, values) {
|
|
|
74
74
|
return map;
|
|
75
75
|
}
|
|
76
76
|
export function evaluateGroupVisibility(group, values) {
|
|
77
|
+
if (group.items && !hasVisibleItems(group.items, values))
|
|
78
|
+
return false;
|
|
77
79
|
if (!group.visibilityCondition?.rules)
|
|
78
80
|
return true;
|
|
79
81
|
const { action = 'show' } = group.visibilityCondition;
|
|
80
82
|
const met = evaluateCondition(group.visibilityCondition, values);
|
|
81
83
|
return action === 'hide' ? !met : met;
|
|
82
84
|
}
|
|
85
|
+
/**
|
|
86
|
+
* A linebreak is always "visible" but renders as a divider only, so a group left with
|
|
87
|
+
* nothing but separators counts as empty.
|
|
88
|
+
*/
|
|
89
|
+
export function hasVisibleItems(items, values) {
|
|
90
|
+
return items.some((item) => item.type !== 'linebreak' && evaluateVisibility(item, values).visible);
|
|
91
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@selvajs/ui",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.2",
|
|
4
4
|
"description": "Shared UI components and utilities for Selva applications",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "VektorNode",
|
|
@@ -58,11 +58,11 @@
|
|
|
58
58
|
"bits-ui": "^2.18.0",
|
|
59
59
|
"svelte": "^5",
|
|
60
60
|
"tailwind-variants": "^3.3.1",
|
|
61
|
-
"three": "^0.
|
|
62
|
-
"@selvajs/compute": "^4.1.
|
|
63
|
-
"@selvajs/visualization": "^1.2.0",
|
|
61
|
+
"three": "^0.186.0",
|
|
62
|
+
"@selvajs/compute": "^4.1.3",
|
|
64
63
|
"@selvajs/schemas": "^5.0.2",
|
|
65
|
-
"@selvajs/
|
|
64
|
+
"@selvajs/visualization": "^1.3.1",
|
|
65
|
+
"@selvajs/solve": "^1.1.1"
|
|
66
66
|
},
|
|
67
67
|
"peerDependenciesMeta": {
|
|
68
68
|
"three": {
|
|
@@ -72,7 +72,7 @@
|
|
|
72
72
|
"dependencies": {
|
|
73
73
|
"@floating-ui/dom": "^1.8.0",
|
|
74
74
|
"@iconify/svelte": "^5.2.1",
|
|
75
|
-
"@lucide/svelte": "^1.
|
|
75
|
+
"@lucide/svelte": "^1.45.0",
|
|
76
76
|
"clsx": "^2.1.1",
|
|
77
77
|
"mode-watcher": "^1.1.0",
|
|
78
78
|
"paneforge": "^1.0.2",
|
|
@@ -81,20 +81,20 @@
|
|
|
81
81
|
"tw-animate-css": "^1.4.0"
|
|
82
82
|
},
|
|
83
83
|
"devDependencies": {
|
|
84
|
-
"@internationalized/date": "^3.12.
|
|
84
|
+
"@internationalized/date": "^3.12.4",
|
|
85
85
|
"@sveltejs/kit": "2.70.3",
|
|
86
86
|
"@sveltejs/vite-plugin-svelte": "^7.3.0",
|
|
87
|
-
"@types/three": "^0.
|
|
88
|
-
"bits-ui": "^2.19.
|
|
87
|
+
"@types/three": "^0.186.0",
|
|
88
|
+
"bits-ui": "^2.19.2",
|
|
89
89
|
"rimraf": "^6.1.3",
|
|
90
|
-
"svelte": "5.
|
|
90
|
+
"svelte": "5.57.0",
|
|
91
91
|
"tailwind-variants": "^3.3.1",
|
|
92
92
|
"vitest": "^4.1.11",
|
|
93
|
-
"@selvajs/compute": "4.1.1",
|
|
94
93
|
"@selvajs/config": "0.0.4",
|
|
95
|
-
"@selvajs/visualization": "1.
|
|
94
|
+
"@selvajs/visualization": "1.3.1",
|
|
96
95
|
"@selvajs/schemas": "5.0.2",
|
|
97
|
-
"@selvajs/
|
|
96
|
+
"@selvajs/compute": "4.1.3",
|
|
97
|
+
"@selvajs/solve": "1.1.1"
|
|
98
98
|
},
|
|
99
99
|
"scripts": {
|
|
100
100
|
"predev": "node ../../scripts/sync-shared-assets.js",
|
|
@@ -42,6 +42,10 @@
|
|
|
42
42
|
dynamicOptions = {}
|
|
43
43
|
}: Props = $props();
|
|
44
44
|
|
|
45
|
+
const visibleGroups = $derived(
|
|
46
|
+
tab.groups.filter((group) => evaluateGroupVisibility(group, values))
|
|
47
|
+
);
|
|
48
|
+
|
|
45
49
|
function getInputById(paramId: string): SchemaInput | undefined {
|
|
46
50
|
return inputs.find((i) => i.id === paramId);
|
|
47
51
|
}
|
|
@@ -82,25 +86,23 @@
|
|
|
82
86
|
<Tabs.Content value={tab.id} class="min-h-0 p-0 flex-1">
|
|
83
87
|
<ScrollArea class="h-full" orientation="vertical">
|
|
84
88
|
<div class="p-4 tab-content-container">
|
|
85
|
-
{#if
|
|
89
|
+
{#if visibleGroups.length === 0}
|
|
86
90
|
<StateDisplay type="empty" size="medium" message={t.tabNoGroups} />
|
|
87
91
|
{:else}
|
|
88
92
|
<div class="gap-8 flex flex-col">
|
|
89
|
-
{#each
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
/>
|
|
103
|
-
{/if}
|
|
93
|
+
{#each visibleGroups as group (group.id)}
|
|
94
|
+
<Group
|
|
95
|
+
label={group.label}
|
|
96
|
+
description={group.description}
|
|
97
|
+
items={group.items}
|
|
98
|
+
columns={group.columns ?? 1}
|
|
99
|
+
collapsed={collapsedGroups[group.id] ?? false}
|
|
100
|
+
{values}
|
|
101
|
+
onToggle={() => onToggleGroup(group.id)}
|
|
102
|
+
inputSnippet={renderInput}
|
|
103
|
+
outputSnippet={renderOutput}
|
|
104
|
+
flat={visibleGroups.length === 1}
|
|
105
|
+
/>
|
|
104
106
|
{/each}
|
|
105
107
|
</div>
|
|
106
108
|
{/if}
|
|
@@ -134,6 +134,8 @@
|
|
|
134
134
|
for (const [layerName, entries] of layerGroups) {
|
|
135
135
|
flat.push({
|
|
136
136
|
kind: 'layer',
|
|
137
|
+
// Prefixed, like the object rows below: a layer row must never share a key with
|
|
138
|
+
// an object row whose identity happens to read like a layer name.
|
|
137
139
|
key: `layer:${layerName}`,
|
|
138
140
|
top,
|
|
139
141
|
height: LAYER_ROW_HEIGHT,
|
|
@@ -145,7 +147,7 @@
|
|
|
145
147
|
for (const entry of entries) {
|
|
146
148
|
flat.push({
|
|
147
149
|
kind: 'object',
|
|
148
|
-
key: entry.
|
|
150
|
+
key: `obj:${entry.rowKey}`,
|
|
149
151
|
top,
|
|
150
152
|
height: OBJECT_ROW_HEIGHT,
|
|
151
153
|
entry
|
|
@@ -106,9 +106,10 @@ export function buildVisibilityMap(
|
|
|
106
106
|
}
|
|
107
107
|
|
|
108
108
|
export function evaluateGroupVisibility(
|
|
109
|
-
group: { visibilityCondition?: GroupVisibilityCondition },
|
|
109
|
+
group: { visibilityCondition?: GroupVisibilityCondition; items?: LayoutItem[] },
|
|
110
110
|
values: Record<string, unknown>
|
|
111
111
|
): boolean {
|
|
112
|
+
if (group.items && !hasVisibleItems(group.items, values)) return false;
|
|
112
113
|
if (!group.visibilityCondition?.rules) return true;
|
|
113
114
|
|
|
114
115
|
const { action = 'show' } = group.visibilityCondition;
|
|
@@ -116,3 +117,13 @@ export function evaluateGroupVisibility(
|
|
|
116
117
|
|
|
117
118
|
return action === 'hide' ? !met : met;
|
|
118
119
|
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* A linebreak is always "visible" but renders as a divider only, so a group left with
|
|
123
|
+
* nothing but separators counts as empty.
|
|
124
|
+
*/
|
|
125
|
+
export function hasVisibleItems(items: LayoutItem[], values: Record<string, unknown>): boolean {
|
|
126
|
+
return items.some(
|
|
127
|
+
(item) => item.type !== 'linebreak' && evaluateVisibility(item, values).visible
|
|
128
|
+
);
|
|
129
|
+
}
|