@sybilion/uilib 1.3.70 → 1.3.71
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/esm/components/ui/Renamer/Renamer.js +4 -3
- package/dist/esm/components/ui/Renamer/Renamer.styl.js +2 -2
- package/dist/esm/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.js +16 -5
- package/dist/esm/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.styl.js +1 -1
- package/dist/esm/types/src/components/ui/WorkspaceAppSwitcher/workspaceApp.types.d.ts +5 -1
- package/package.json +1 -1
- package/src/components/ui/Renamer/Renamer.styl +21 -5
- package/src/components/ui/Renamer/Renamer.styl.d.ts +1 -0
- package/src/components/ui/Renamer/Renamer.tsx +5 -4
- package/src/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.styl +8 -0
- package/src/components/ui/WorkspaceAppSwitcher/WorkspaceAppSwitcher.tsx +27 -4
- package/src/components/ui/WorkspaceAppSwitcher/workspaceApp.types.ts +6 -1
|
@@ -45,17 +45,18 @@ function Renamer({ value = '', onInput, onChange, children, className, placehold
|
|
|
45
45
|
setName(value);
|
|
46
46
|
setIsRenaming(true);
|
|
47
47
|
}, [value]);
|
|
48
|
-
const
|
|
48
|
+
const inputSizeMap = {
|
|
49
49
|
sm: 'sm',
|
|
50
50
|
md: 'md',
|
|
51
|
-
lg
|
|
51
|
+
// lg typography comes from Renamer `.size-lg`; avoid Input size-lg (text-base).
|
|
52
|
+
lg: 'md',
|
|
52
53
|
};
|
|
53
54
|
const buttonSizeMap = {
|
|
54
55
|
sm: 'sm',
|
|
55
56
|
md: 'md',
|
|
56
57
|
lg: 'lg',
|
|
57
58
|
};
|
|
58
|
-
return (jsx("div", { className: cn(S.root, !value && S.empty, className), onKeyDown: onKeyDown, children: isRenaming ? (jsx(Input, { className: S.input, autoFocus: !isMobile, variant: "clean", size:
|
|
59
|
+
return (jsx("div", { className: cn(S.root, S[`size-${size}`], !value && S.empty, className), onKeyDown: onKeyDown, children: isRenaming ? (jsx(Input, { className: S.input, autoFocus: !isMobile, variant: "clean", size: inputSizeMap[size], placeholder: placeholder, value: name, onChange: handleInputChange, onBlur: handleBlur, onKeyDown: onKeyDown })) : (jsxs(Fragment, { children: [jsx("span", { className: S.value, children: children }), jsxs(Tooltip, { children: [jsx(TooltipTrigger, { asChild: true, children: jsx(Button, { className: S.button, variant: "ghost", onPointerDown: e => {
|
|
59
60
|
e.preventDefault();
|
|
60
61
|
e.stopPropagation();
|
|
61
62
|
}, onClick: e => {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = ".Renamer_root__26OvT{align-items:center;display:flex}.Renamer_value__G8b1D{padding-right:var(--p-2)}.Renamer_input__KRnGn
|
|
4
|
-
var S = {"root":"Renamer_root__26OvT","value":"Renamer_value__G8b1D","input":"Renamer_input__KRnGn","empty":"Renamer_empty__A7xx1","button":"Renamer_button__jKMLc"};
|
|
3
|
+
var css_248z = ".Renamer_root__26OvT{align-items:center;display:flex}.Renamer_value__G8b1D{padding-right:var(--p-2)}.Renamer_size-lg__dfVhW.Renamer_root__26OvT .Renamer_input__KRnGn,.Renamer_size-lg__dfVhW.Renamer_root__26OvT .Renamer_value__G8b1D{color:var(--foreground);font-family:var(--font-family-heading);font-size:var(--text-2xl);font-weight:300;line-height:var(--text-2xl)}.Renamer_size-lg__dfVhW.Renamer_root__26OvT .Renamer_input__KRnGn{border-radius:var(--p-4);box-shadow:0 0 0 1px var(--border);height:auto;min-height:var(--text-2xl);padding:4px 12px 4px 0}.Renamer_empty__A7xx1.Renamer_size-lg__dfVhW.Renamer_root__26OvT .Renamer_input__KRnGn{background-color:var(--accent)/.1}.Renamer_button__jKMLc{opacity:.5;padding-left:0;transition:opacity .2s ease-out}.Renamer_root__26OvT:hover .Renamer_button__jKMLc{opacity:1}";
|
|
4
|
+
var S = {"root":"Renamer_root__26OvT","value":"Renamer_value__G8b1D","size-lg":"Renamer_size-lg__dfVhW","input":"Renamer_input__KRnGn","empty":"Renamer_empty__A7xx1","button":"Renamer_button__jKMLc"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
7
7
|
export { S as default };
|
|
@@ -12,12 +12,23 @@ import S from './WorkspaceAppSwitcher.styl.js';
|
|
|
12
12
|
function entryKey(entry) {
|
|
13
13
|
return entry.id;
|
|
14
14
|
}
|
|
15
|
-
function
|
|
16
|
-
|
|
15
|
+
function renderIconContent(icon, iconKey) {
|
|
16
|
+
if (icon != null) {
|
|
17
|
+
return (jsx("span", { className: S.icon, "aria-hidden": true, children: icon }));
|
|
18
|
+
}
|
|
19
|
+
if (iconKey != null) {
|
|
20
|
+
const IconComponent = WORKSPACE_APP_ICONS[iconKey];
|
|
21
|
+
if (IconComponent) {
|
|
22
|
+
return jsx(IconComponent, { className: S.icon, "aria-hidden": true });
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
function IconTile({ icon, iconKey, accentMuted, accent, }) {
|
|
17
28
|
return (jsx("span", { className: S.iconTile, style: {
|
|
18
29
|
'--bg-color': accentMuted,
|
|
19
30
|
'--fg-color': accent,
|
|
20
|
-
}, children:
|
|
31
|
+
}, children: renderIconContent(icon, iconKey) }));
|
|
21
32
|
}
|
|
22
33
|
function useResolvedApps(appsStorageKey, defaultApps) {
|
|
23
34
|
const [apps, setApps] = useState(() => {
|
|
@@ -51,11 +62,11 @@ function WorkspaceAppSwitcher({ pathname, onNavigate, authenticated = true, defa
|
|
|
51
62
|
if (!displayApp) {
|
|
52
63
|
return null;
|
|
53
64
|
}
|
|
54
|
-
return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button, { variant: "ghost", className: S.trigger, "aria-label": "Select workspace app", children: [jsx(IconTile, { iconKey: displayApp.iconKey, accentMuted: displayApp.accentMuted, accent: displayApp.accent }), jsxs("span", { className: S.textCol, children: [jsx("span", { className: S.name, children: displayApp.displayName }), jsx("span", { className: S.sub, children: displayApp.subtitle })] }), jsx(ChevronDown, { className: S.chevron, size: 12, "aria-hidden": true })] }) }), jsx(DropdownMenuContent, { className: S.menuContent, align: "start", sideOffset: 8, elevation: "md", children: apps.map(entry => {
|
|
65
|
+
return (jsxs(DropdownMenu, { children: [jsx(DropdownMenuTrigger, { asChild: true, children: jsxs(Button, { variant: "ghost", className: S.trigger, "aria-label": "Select workspace app", children: [jsx(IconTile, { icon: displayApp.icon, iconKey: displayApp.iconKey, accentMuted: displayApp.accentMuted, accent: displayApp.accent }), jsxs("span", { className: S.textCol, children: [jsx("span", { className: S.name, children: displayApp.displayName }), jsx("span", { className: S.sub, children: displayApp.subtitle })] }), jsx(ChevronDown, { className: S.chevron, size: 12, "aria-hidden": true })] }) }), jsx(DropdownMenuContent, { className: S.menuContent, align: "start", sideOffset: 8, elevation: "md", children: apps.map(entry => {
|
|
55
66
|
const active = current != null ? entryKey(entry) === entryKey(current) : false;
|
|
56
67
|
return (jsxs(DropdownMenuItem, { className: cn(S.item, active && S.itemActive), onSelect: () => {
|
|
57
68
|
onNavigate(entry.href);
|
|
58
|
-
}, children: [jsx(IconTile, { iconKey: entry.iconKey, accentMuted: entry.accentMuted, accent: entry.accent }), jsxs("span", { className: S.textCol, children: [jsx("span", { className: S.name, children: entry.displayName }), jsx("span", { className: S.sub, children: entry.subtitle })] })] }, entry.id));
|
|
69
|
+
}, children: [jsx(IconTile, { icon: entry.icon, iconKey: entry.iconKey, accentMuted: entry.accentMuted, accent: entry.accent }), jsxs("span", { className: S.textCol, children: [jsx("span", { className: S.name, children: entry.displayName }), jsx("span", { className: S.sub, children: entry.subtitle })] })] }, entry.id));
|
|
59
70
|
}) })] }));
|
|
60
71
|
}
|
|
61
72
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import styleInject from 'style-inject';
|
|
2
2
|
|
|
3
|
-
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.WorkspaceAppSwitcher_trigger__s6qYT{align-items:center;background:transparent;border:none;border-radius:12px;color:inherit;cursor:pointer;display:flex;font:inherit;gap:var(--p-2);height:auto;margin-left:var(--p-3)!important;max-width:320px;padding:var(--p-1)!important;padding-right:var(--p-3)!important;text-align:left}.WorkspaceAppSwitcher_trigger__s6qYT:hover{background-color:var(--muted)}@media (max-width:768px){.WorkspaceAppSwitcher_trigger__s6qYT{gap:0;margin-left:0!important;max-width:none;padding-right:var(--p-1)!important}.WorkspaceAppSwitcher_trigger__s6qYT .WorkspaceAppSwitcher_chevron__7kAqO,.WorkspaceAppSwitcher_trigger__s6qYT .WorkspaceAppSwitcher_textCol__K1gfI{display:none}}.WorkspaceAppSwitcher_iconTile__tVDr8{align-items:center;border-radius:10px;color:var(--fg-color);display:flex;flex-shrink:0;height:40px;justify-content:center;position:relative;width:40px}.WorkspaceAppSwitcher_iconTile__tVDr8:after,.WorkspaceAppSwitcher_iconTile__tVDr8:before{border-radius:inherit;content:\"\";display:block;height:100%;position:absolute;width:100%}.WorkspaceAppSwitcher_iconTile__tVDr8:before{background-color:var(--background)}.WorkspaceAppSwitcher_iconTile__tVDr8:after{background-color:var(--bg-color)}.WorkspaceAppSwitcher_icon__Jgw14{color:var(--fg-color)!important;height:22px!important;width:22px!important
|
|
3
|
+
var css_248z = "@media (max-width:768px){:root{--page-x-padding:var(--p-6);--page-y-padding:var(--p-6)}}.WorkspaceAppSwitcher_trigger__s6qYT{align-items:center;background:transparent;border:none;border-radius:12px;color:inherit;cursor:pointer;display:flex;font:inherit;gap:var(--p-2);height:auto;margin-left:var(--p-3)!important;max-width:320px;padding:var(--p-1)!important;padding-right:var(--p-3)!important;text-align:left}.WorkspaceAppSwitcher_trigger__s6qYT:hover{background-color:var(--muted)}@media (max-width:768px){.WorkspaceAppSwitcher_trigger__s6qYT{gap:0;margin-left:0!important;max-width:none;padding-right:var(--p-1)!important}.WorkspaceAppSwitcher_trigger__s6qYT .WorkspaceAppSwitcher_chevron__7kAqO,.WorkspaceAppSwitcher_trigger__s6qYT .WorkspaceAppSwitcher_textCol__K1gfI{display:none}}.WorkspaceAppSwitcher_iconTile__tVDr8{align-items:center;border-radius:10px;color:var(--fg-color);display:flex;flex-shrink:0;height:40px;justify-content:center;position:relative;width:40px}.WorkspaceAppSwitcher_iconTile__tVDr8:after,.WorkspaceAppSwitcher_iconTile__tVDr8:before{border-radius:inherit;content:\"\";display:block;height:100%;position:absolute;width:100%}.WorkspaceAppSwitcher_iconTile__tVDr8:before{background-color:var(--background)}.WorkspaceAppSwitcher_iconTile__tVDr8:after{background-color:var(--bg-color)}.WorkspaceAppSwitcher_icon__Jgw14{align-items:center;display:flex;justify-content:center;z-index:1}.WorkspaceAppSwitcher_icon__Jgw14,.WorkspaceAppSwitcher_icon__Jgw14 svg{color:var(--fg-color)!important;height:22px!important;width:22px!important}.WorkspaceAppSwitcher_textCol__K1gfI{display:flex;flex:1;flex-direction:column;gap:2px;min-width:0}.WorkspaceAppSwitcher_name__ewMYP{color:var(--foreground);font-size:var(--text-sm);font-weight:600}.WorkspaceAppSwitcher_name__ewMYP,.WorkspaceAppSwitcher_sub__b7w1p{line-height:1.2;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.WorkspaceAppSwitcher_sub__b7w1p{color:var(--muted-foreground);font-size:var(--text-xs)}.WorkspaceAppSwitcher_menuContent__4-UNY{max-width:360px;min-width:280px}.WorkspaceAppSwitcher_item__nnufY{align-items:center;cursor:pointer;display:flex;gap:var(--p-3);outline:none;padding:var(--p-3)}.WorkspaceAppSwitcher_itemActive__3mPlO{background-color:var(--muted)}";
|
|
4
4
|
var S = {"trigger":"WorkspaceAppSwitcher_trigger__s6qYT","textCol":"WorkspaceAppSwitcher_textCol__K1gfI","chevron":"WorkspaceAppSwitcher_chevron__7kAqO","iconTile":"WorkspaceAppSwitcher_iconTile__tVDr8","icon":"WorkspaceAppSwitcher_icon__Jgw14","name":"WorkspaceAppSwitcher_name__ewMYP","sub":"WorkspaceAppSwitcher_sub__b7w1p","menuContent":"WorkspaceAppSwitcher_menuContent__4-UNY","item":"WorkspaceAppSwitcher_item__nnufY","itemActive":"WorkspaceAppSwitcher_itemActive__3mPlO"};
|
|
5
5
|
styleInject(css_248z);
|
|
6
6
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
1
2
|
import type { WorkspaceAppIconKey } from './workspaceAppIcons';
|
|
2
3
|
/** Path segment for slug apps: pathname matches `/apps/{id}` */
|
|
3
4
|
export declare const WORKSPACE_APP_SLUG_BASE_PATH = "/apps";
|
|
@@ -7,7 +8,10 @@ export type WorkspaceAppEntry = {
|
|
|
7
8
|
id: string;
|
|
8
9
|
displayName: string;
|
|
9
10
|
subtitle: string;
|
|
10
|
-
|
|
11
|
+
/** Custom icon for display; not persisted to localStorage. */
|
|
12
|
+
icon?: ReactNode;
|
|
13
|
+
/** Built-in icon lookup when `icon` is omitted (required for localStorage entries). */
|
|
14
|
+
iconKey?: WorkspaceAppIconKey;
|
|
11
15
|
accent: string;
|
|
12
16
|
accentMuted: string;
|
|
13
17
|
href: string;
|
package/package.json
CHANGED
|
@@ -5,12 +5,28 @@
|
|
|
5
5
|
.value
|
|
6
6
|
padding-right var(--p-2)
|
|
7
7
|
|
|
8
|
-
.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
8
|
+
// Matches PageHeader .title h1 typography (page title context).
|
|
9
|
+
.size-lg.root
|
|
10
|
+
.value
|
|
11
|
+
font-family var(--font-family-heading)
|
|
12
|
+
font-weight 300
|
|
13
|
+
font-size var(--text-2xl)
|
|
14
|
+
line-height var(--text-2xl)
|
|
15
|
+
color var(--foreground)
|
|
12
16
|
|
|
13
|
-
.
|
|
17
|
+
.input
|
|
18
|
+
font-family var(--font-family-heading)
|
|
19
|
+
font-weight 300
|
|
20
|
+
font-size var(--text-2xl)
|
|
21
|
+
line-height var(--text-2xl)
|
|
22
|
+
color var(--foreground)
|
|
23
|
+
height auto
|
|
24
|
+
min-height var(--text-2xl)
|
|
25
|
+
padding 4px 12px 4px 0
|
|
26
|
+
border-radius var(--p-4)
|
|
27
|
+
box-shadow 0 0 0 1px var(--border)
|
|
28
|
+
|
|
29
|
+
.empty.size-lg.root .input
|
|
14
30
|
background-color var(--accent) / 0.1
|
|
15
31
|
|
|
16
32
|
.button
|
|
@@ -74,10 +74,11 @@ export function Renamer({
|
|
|
74
74
|
setIsRenaming(true);
|
|
75
75
|
}, [value]);
|
|
76
76
|
|
|
77
|
-
const
|
|
77
|
+
const inputSizeMap = {
|
|
78
78
|
sm: 'sm' as const,
|
|
79
79
|
md: 'md' as const,
|
|
80
|
-
lg
|
|
80
|
+
// lg typography comes from Renamer `.size-lg`; avoid Input size-lg (text-base).
|
|
81
|
+
lg: 'md' as const,
|
|
81
82
|
};
|
|
82
83
|
|
|
83
84
|
const buttonSizeMap = {
|
|
@@ -88,7 +89,7 @@ export function Renamer({
|
|
|
88
89
|
|
|
89
90
|
return (
|
|
90
91
|
<div
|
|
91
|
-
className={cn(S.root, !value && S.empty, className)}
|
|
92
|
+
className={cn(S.root, S[`size-${size}`], !value && S.empty, className)}
|
|
92
93
|
onKeyDown={onKeyDown}
|
|
93
94
|
>
|
|
94
95
|
{isRenaming ? (
|
|
@@ -96,7 +97,7 @@ export function Renamer({
|
|
|
96
97
|
className={S.input}
|
|
97
98
|
autoFocus={!isMobile}
|
|
98
99
|
variant="clean"
|
|
99
|
-
size={
|
|
100
|
+
size={inputSizeMap[size]}
|
|
100
101
|
placeholder={placeholder}
|
|
101
102
|
value={name}
|
|
102
103
|
onChange={handleInputChange}
|
|
@@ -59,10 +59,18 @@
|
|
|
59
59
|
|
|
60
60
|
.icon
|
|
61
61
|
z-index 1
|
|
62
|
+
display flex
|
|
63
|
+
align-items center
|
|
64
|
+
justify-content center
|
|
62
65
|
width 22px !important
|
|
63
66
|
height 22px !important
|
|
64
67
|
color var(--fg-color) !important
|
|
65
68
|
|
|
69
|
+
:global(svg)
|
|
70
|
+
width 22px !important
|
|
71
|
+
height 22px !important
|
|
72
|
+
color var(--fg-color) !important
|
|
73
|
+
|
|
66
74
|
.textCol
|
|
67
75
|
display flex
|
|
68
76
|
flex-direction column
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import cn from 'classnames';
|
|
2
|
-
import type { CSSProperties } from 'react';
|
|
2
|
+
import type { CSSProperties, ReactNode } from 'react';
|
|
3
3
|
import { useEffect, useState } from 'react';
|
|
4
4
|
|
|
5
5
|
import { Button } from '#uilib/components/ui/Button/Button';
|
|
@@ -32,16 +32,37 @@ function entryKey(entry: WorkspaceAppEntry): string {
|
|
|
32
32
|
return entry.id;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
+
function renderIconContent(
|
|
36
|
+
icon: ReactNode | undefined,
|
|
37
|
+
iconKey: WorkspaceAppEntry['iconKey'],
|
|
38
|
+
): ReactNode {
|
|
39
|
+
if (icon != null) {
|
|
40
|
+
return (
|
|
41
|
+
<span className={S.icon} aria-hidden>
|
|
42
|
+
{icon}
|
|
43
|
+
</span>
|
|
44
|
+
);
|
|
45
|
+
}
|
|
46
|
+
if (iconKey != null) {
|
|
47
|
+
const IconComponent = WORKSPACE_APP_ICONS[iconKey];
|
|
48
|
+
if (IconComponent) {
|
|
49
|
+
return <IconComponent className={S.icon} aria-hidden />;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
|
|
35
55
|
function IconTile({
|
|
56
|
+
icon,
|
|
36
57
|
iconKey,
|
|
37
58
|
accentMuted,
|
|
38
59
|
accent,
|
|
39
60
|
}: {
|
|
40
|
-
|
|
61
|
+
icon?: ReactNode;
|
|
62
|
+
iconKey?: WorkspaceAppEntry['iconKey'];
|
|
41
63
|
accentMuted: string;
|
|
42
64
|
accent: string;
|
|
43
65
|
}) {
|
|
44
|
-
const IconComponent = WORKSPACE_APP_ICONS[iconKey];
|
|
45
66
|
return (
|
|
46
67
|
<span
|
|
47
68
|
className={S.iconTile}
|
|
@@ -52,7 +73,7 @@ function IconTile({
|
|
|
52
73
|
} as CSSProperties
|
|
53
74
|
}
|
|
54
75
|
>
|
|
55
|
-
|
|
76
|
+
{renderIconContent(icon, iconKey)}
|
|
56
77
|
</span>
|
|
57
78
|
);
|
|
58
79
|
}
|
|
@@ -116,6 +137,7 @@ export function WorkspaceAppSwitcher({
|
|
|
116
137
|
aria-label="Select workspace app"
|
|
117
138
|
>
|
|
118
139
|
<IconTile
|
|
140
|
+
icon={displayApp.icon}
|
|
119
141
|
iconKey={displayApp.iconKey}
|
|
120
142
|
accentMuted={displayApp.accentMuted}
|
|
121
143
|
accent={displayApp.accent}
|
|
@@ -146,6 +168,7 @@ export function WorkspaceAppSwitcher({
|
|
|
146
168
|
}}
|
|
147
169
|
>
|
|
148
170
|
<IconTile
|
|
171
|
+
icon={entry.icon}
|
|
149
172
|
iconKey={entry.iconKey}
|
|
150
173
|
accentMuted={entry.accentMuted}
|
|
151
174
|
accent={entry.accent}
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
|
|
1
3
|
import type { WorkspaceAppIconKey } from './workspaceAppIcons';
|
|
2
4
|
|
|
3
5
|
/** Path segment for slug apps: pathname matches `/apps/{id}` */
|
|
@@ -9,7 +11,10 @@ export type WorkspaceAppEntry = {
|
|
|
9
11
|
id: string;
|
|
10
12
|
displayName: string;
|
|
11
13
|
subtitle: string;
|
|
12
|
-
|
|
14
|
+
/** Custom icon for display; not persisted to localStorage. */
|
|
15
|
+
icon?: ReactNode;
|
|
16
|
+
/** Built-in icon lookup when `icon` is omitted (required for localStorage entries). */
|
|
17
|
+
iconKey?: WorkspaceAppIconKey;
|
|
13
18
|
accent: string;
|
|
14
19
|
accentMuted: string;
|
|
15
20
|
href: string;
|