@dxos/react-ui-pickers 0.8.4-main.b97322e → 0.8.4-main.bcb3aa67d6
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/lib/browser/chunk-IEOELSPW.mjs +64 -0
- package/dist/lib/browser/chunk-IEOELSPW.mjs.map +7 -0
- package/dist/lib/browser/components/IconPicker/icons.mjs +9 -0
- package/dist/lib/browser/components/IconPicker/icons.mjs.map +7 -0
- package/dist/lib/browser/index.css +2 -2
- package/dist/lib/browser/index.css.map +2 -2
- package/dist/lib/browser/index.mjs +195 -295
- package/dist/lib/browser/index.mjs.map +3 -3
- package/dist/lib/browser/meta.json +1 -1
- package/dist/lib/node-esm/chunk-OLGXN23I.mjs +66 -0
- package/dist/lib/node-esm/chunk-OLGXN23I.mjs.map +7 -0
- package/dist/lib/node-esm/components/IconPicker/icons.mjs +10 -0
- package/dist/lib/node-esm/components/IconPicker/icons.mjs.map +7 -0
- package/dist/lib/node-esm/index.css +2 -2
- package/dist/lib/node-esm/index.css.map +2 -2
- package/dist/lib/node-esm/index.mjs +194 -295
- package/dist/lib/node-esm/index.mjs.map +3 -3
- package/dist/lib/node-esm/meta.json +1 -1
- package/dist/types/src/components/EmojiPicker/EmojiPicker.d.ts.map +1 -1
- package/dist/types/src/components/EmojiPicker/EmojiPicker.stories.d.ts +8 -4
- package/dist/types/src/components/EmojiPicker/EmojiPicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/HuePicker/HuePicker.d.ts.map +1 -1
- package/dist/types/src/components/HuePicker/HuePicker.stories.d.ts +10 -4
- package/dist/types/src/components/HuePicker/HuePicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/IconPicker/IconPicker.d.ts +1 -1
- package/dist/types/src/components/IconPicker/IconPicker.d.ts.map +1 -1
- package/dist/types/src/components/IconPicker/IconPicker.stories.d.ts +10 -4
- package/dist/types/src/components/IconPicker/IconPicker.stories.d.ts.map +1 -1
- package/dist/types/src/components/IconPicker/icons.d.ts +7 -0
- package/dist/types/src/components/IconPicker/icons.d.ts.map +1 -0
- package/dist/types/src/components/PickerButton/PickerButton.d.ts +3 -3
- package/dist/types/src/components/PickerButton/PickerButton.d.ts.map +1 -1
- package/dist/types/tsconfig.tsbuildinfo +1 -1
- package/package.json +32 -18
- package/src/components/EmojiPicker/EmojiPicker.stories.tsx +12 -15
- package/src/components/EmojiPicker/EmojiPicker.tsx +27 -22
- package/src/components/EmojiPicker/emoji.css +5 -21
- package/src/components/HuePicker/HuePicker.stories.tsx +10 -12
- package/src/components/HuePicker/HuePicker.tsx +8 -12
- package/src/components/IconPicker/IconPicker.stories.tsx +10 -12
- package/src/components/IconPicker/IconPicker.tsx +8 -62
- package/src/components/IconPicker/icons.ts +66 -0
- package/src/components/PickerButton/PickerButton.tsx +11 -12
package/package.json
CHANGED
|
@@ -1,22 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@dxos/react-ui-pickers",
|
|
3
|
-
"version": "0.8.4-main.
|
|
3
|
+
"version": "0.8.4-main.bcb3aa67d6",
|
|
4
4
|
"description": "A collection of picker components.",
|
|
5
5
|
"homepage": "https://dxos.org",
|
|
6
6
|
"bugs": "https://github.com/dxos/dxos/issues",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/dxos/dxos"
|
|
10
|
+
},
|
|
7
11
|
"license": "MIT",
|
|
8
12
|
"author": "DXOS.org",
|
|
9
13
|
"type": "module",
|
|
10
14
|
"exports": {
|
|
11
15
|
".": {
|
|
16
|
+
"source": "./src/index.ts",
|
|
12
17
|
"types": "./dist/types/src/index.d.ts",
|
|
13
18
|
"browser": "./dist/lib/browser/index.mjs",
|
|
14
19
|
"node": "./dist/lib/node-esm/index.mjs"
|
|
20
|
+
},
|
|
21
|
+
"./icons": {
|
|
22
|
+
"source": "./src/components/IconPicker/icons.ts",
|
|
23
|
+
"types": "./dist/types/src/components/IconPicker/icons.d.ts",
|
|
24
|
+
"browser": "./dist/lib/browser/components/IconPicker/icons.mjs",
|
|
25
|
+
"node": "./dist/lib/node-esm/components/IconPicker/icons.mjs"
|
|
15
26
|
}
|
|
16
27
|
},
|
|
17
28
|
"types": "dist/types/src/index.d.ts",
|
|
18
29
|
"typesVersions": {
|
|
19
|
-
"*": {
|
|
30
|
+
"*": {
|
|
31
|
+
"icons": [
|
|
32
|
+
"./dist/types/src/components/IconPicker/icons.d.ts"
|
|
33
|
+
]
|
|
34
|
+
}
|
|
20
35
|
},
|
|
21
36
|
"files": [
|
|
22
37
|
"dist",
|
|
@@ -25,28 +40,27 @@
|
|
|
25
40
|
"dependencies": {
|
|
26
41
|
"@emoji-mart/data": "^1.1.2",
|
|
27
42
|
"@emoji-mart/react": "^1.1.1",
|
|
28
|
-
"@preact-signals/safe-react": "^0.9.0",
|
|
29
43
|
"@radix-ui/react-use-controllable-state": "1.1.0",
|
|
30
44
|
"react-resize-detector": "^11.0.1",
|
|
31
|
-
"@dxos/log": "0.8.4-main.
|
|
32
|
-
"@dxos/
|
|
33
|
-
"@dxos/
|
|
45
|
+
"@dxos/log": "0.8.4-main.bcb3aa67d6",
|
|
46
|
+
"@dxos/util": "0.8.4-main.bcb3aa67d6",
|
|
47
|
+
"@dxos/ui-types": "0.8.4-main.bcb3aa67d6"
|
|
34
48
|
},
|
|
35
49
|
"devDependencies": {
|
|
36
|
-
"@types/react": "~
|
|
37
|
-
"@types/react-dom": "~
|
|
38
|
-
"react": "~
|
|
39
|
-
"react-dom": "~
|
|
40
|
-
"vite": "
|
|
41
|
-
"@dxos/
|
|
42
|
-
"@dxos/
|
|
43
|
-
"@dxos/
|
|
50
|
+
"@types/react": "~19.2.7",
|
|
51
|
+
"@types/react-dom": "~19.2.3",
|
|
52
|
+
"react": "~19.2.3",
|
|
53
|
+
"react-dom": "~19.2.3",
|
|
54
|
+
"vite": "^7.1.11",
|
|
55
|
+
"@dxos/storybook-utils": "0.8.4-main.bcb3aa67d6",
|
|
56
|
+
"@dxos/ui-theme": "0.8.4-main.bcb3aa67d6",
|
|
57
|
+
"@dxos/react-ui": "0.8.4-main.bcb3aa67d6"
|
|
44
58
|
},
|
|
45
59
|
"peerDependencies": {
|
|
46
|
-
"react": "~
|
|
47
|
-
"react-dom": "~
|
|
48
|
-
"@dxos/
|
|
49
|
-
"@dxos/react-ui
|
|
60
|
+
"react": "~19.2.3",
|
|
61
|
+
"react-dom": "~19.2.3",
|
|
62
|
+
"@dxos/ui-theme": "0.8.4-main.bcb3aa67d6",
|
|
63
|
+
"@dxos/react-ui": "0.8.4-main.bcb3aa67d6"
|
|
50
64
|
},
|
|
51
65
|
"publishConfig": {
|
|
52
66
|
"access": "public"
|
|
@@ -2,15 +2,22 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@
|
|
6
|
-
|
|
5
|
+
import EmojiPicker from '@emoji-mart/react';
|
|
7
6
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
7
|
import React, { useState } from 'react';
|
|
9
8
|
|
|
10
9
|
import { Toolbar } from '@dxos/react-ui';
|
|
11
|
-
import { withLayout, withTheme } from '@dxos/
|
|
10
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
11
|
+
|
|
12
|
+
import { EmojiPickerBlock, type EmojiPickerProps, EmojiPickerToolbarButton } from './EmojiPicker';
|
|
13
|
+
|
|
14
|
+
const meta = {
|
|
15
|
+
title: 'ui/react-ui-pickers/EmojiPicker',
|
|
16
|
+
component: EmojiPicker,
|
|
17
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
18
|
+
} satisfies Meta<typeof EmojiPicker>;
|
|
12
19
|
|
|
13
|
-
|
|
20
|
+
export default meta;
|
|
14
21
|
|
|
15
22
|
const ToolbarButtonStory = (props: EmojiPickerProps) => {
|
|
16
23
|
const [emoji, setEmoji] = useState<string>(props.defaultEmoji ?? '😀');
|
|
@@ -26,7 +33,7 @@ const BlockStory = (props: EmojiPickerProps) => {
|
|
|
26
33
|
const [emoji, setEmoji] = useState<string>(props.defaultEmoji ?? '😀');
|
|
27
34
|
|
|
28
35
|
return (
|
|
29
|
-
<div
|
|
36
|
+
<div>
|
|
30
37
|
<EmojiPickerBlock
|
|
31
38
|
{...props}
|
|
32
39
|
emoji={emoji}
|
|
@@ -50,13 +57,3 @@ export const Block: StoryObj<EmojiPickerProps> = {
|
|
|
50
57
|
defaultEmoji: '😀',
|
|
51
58
|
},
|
|
52
59
|
};
|
|
53
|
-
|
|
54
|
-
const meta: Meta = {
|
|
55
|
-
title: 'ui/react-ui-pickers/EmojiPicker',
|
|
56
|
-
decorators: [withTheme, withLayout()],
|
|
57
|
-
parameters: {
|
|
58
|
-
layout: 'centered',
|
|
59
|
-
},
|
|
60
|
-
};
|
|
61
|
-
|
|
62
|
-
export default meta;
|
|
@@ -9,17 +9,18 @@ import React, { useState } from 'react';
|
|
|
9
9
|
|
|
10
10
|
import {
|
|
11
11
|
Button,
|
|
12
|
+
ButtonGroup,
|
|
12
13
|
type ButtonProps,
|
|
14
|
+
Icon,
|
|
15
|
+
IconButton,
|
|
13
16
|
Popover,
|
|
14
17
|
type ThemedClassName,
|
|
15
18
|
Toolbar,
|
|
16
|
-
Tooltip,
|
|
17
19
|
useMediaQuery,
|
|
18
20
|
useThemeContext,
|
|
19
21
|
useTranslation,
|
|
20
|
-
Icon,
|
|
21
|
-
ButtonGroup,
|
|
22
22
|
} from '@dxos/react-ui';
|
|
23
|
+
import { osTranslations } from '@dxos/ui-theme';
|
|
23
24
|
|
|
24
25
|
import './emoji.css';
|
|
25
26
|
|
|
@@ -42,7 +43,7 @@ export const EmojiPickerToolbarButton = ({
|
|
|
42
43
|
defaultEmoji,
|
|
43
44
|
onChangeEmoji,
|
|
44
45
|
}: Omit<EmojiPickerProps, 'onClickClear'>) => {
|
|
45
|
-
const { t } = useTranslation(
|
|
46
|
+
const { t } = useTranslation(osTranslations);
|
|
46
47
|
const { themeMode } = useThemeContext();
|
|
47
48
|
|
|
48
49
|
const [_emojiValue, setEmojiValue] = useControllableState<string>({
|
|
@@ -60,14 +61,15 @@ export const EmojiPickerToolbarButton = ({
|
|
|
60
61
|
setEmojiPickerOpen(nextOpen);
|
|
61
62
|
}}
|
|
62
63
|
>
|
|
63
|
-
<
|
|
64
|
-
<
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
<Popover.Trigger asChild>
|
|
65
|
+
<Toolbar.IconButton
|
|
66
|
+
icon='ph--user-circle--regular'
|
|
67
|
+
label={t('select-emoji.label')}
|
|
68
|
+
iconOnly
|
|
69
|
+
tooltipSide='bottom'
|
|
70
|
+
disabled={disabled}
|
|
71
|
+
/>
|
|
72
|
+
</Popover.Trigger>
|
|
71
73
|
<Popover.Portal>
|
|
72
74
|
<Popover.Content
|
|
73
75
|
side='bottom'
|
|
@@ -111,8 +113,8 @@ export const EmojiPickerBlock = ({
|
|
|
111
113
|
triggerVariant = 'ghost',
|
|
112
114
|
classNames,
|
|
113
115
|
}: EmojiPickerProps) => {
|
|
114
|
-
const { t } = useTranslation(
|
|
115
|
-
const [isMd] = useMediaQuery('md'
|
|
116
|
+
const { t } = useTranslation(osTranslations);
|
|
117
|
+
const [isMd] = useMediaQuery('md');
|
|
116
118
|
|
|
117
119
|
const [emojiValue, setEmojiValue] = useControllableState<string>({
|
|
118
120
|
prop: emoji,
|
|
@@ -126,8 +128,8 @@ export const EmojiPickerBlock = ({
|
|
|
126
128
|
<ButtonGroup classNames={classNames}>
|
|
127
129
|
<Popover.Root open={emojiPickerOpen} onOpenChange={setEmojiPickerOpen}>
|
|
128
130
|
<Popover.Trigger asChild>
|
|
129
|
-
<Button variant={triggerVariant} classNames='grow gap-2 text-2xl
|
|
130
|
-
<span className='sr-only'>{t('select
|
|
131
|
+
<Button variant={triggerVariant} classNames='grow gap-2 text-2xl py-1' disabled={disabled}>
|
|
132
|
+
<span className='sr-only'>{t('select-emoji.label')}</span>
|
|
131
133
|
<span>{emojiValue}</span>
|
|
132
134
|
<Icon icon='ph--caret-down--bold' size={3} />
|
|
133
135
|
</Button>
|
|
@@ -157,12 +159,15 @@ export const EmojiPickerBlock = ({
|
|
|
157
159
|
<Popover.Arrow />
|
|
158
160
|
</Popover.Content>
|
|
159
161
|
</Popover.Root>
|
|
160
|
-
<
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
162
|
+
<IconButton
|
|
163
|
+
icon='ph--arrow-counter-clockwise--regular'
|
|
164
|
+
iconOnly
|
|
165
|
+
label={t('clear.label')}
|
|
166
|
+
tooltipSide='right'
|
|
167
|
+
variant={triggerVariant}
|
|
168
|
+
onClick={onClickClear}
|
|
169
|
+
disabled={disabled}
|
|
170
|
+
/>
|
|
166
171
|
</ButtonGroup>
|
|
167
172
|
);
|
|
168
173
|
};
|
|
@@ -1,25 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* https://github.com/missive/emoji-mart/blob/main/packages/emoji-mart-website/example-custom-styles.html
|
|
3
3
|
*/
|
|
4
|
-
[data-theme=
|
|
5
|
-
/* TODO(burdon):
|
|
6
|
-
--background-rgb: #
|
|
7
|
-
--rgb-background: #
|
|
8
|
-
|
|
9
|
-
--font-family: "Inter Variable", ui-sans-serif;
|
|
10
|
-
|
|
11
|
-
/*--font-size: 16px;*/
|
|
12
|
-
/*--color-border-over: rgba(0, 0, 0, 0.1);*/
|
|
13
|
-
/*--color-border: rgba(0, 0, 0, 0.05);*/
|
|
14
|
-
/*--category-icon-size: 24px;*/
|
|
15
|
-
/*--border-radius: 24px;*/
|
|
16
|
-
/*--font-family: 'Comic Sans MS', 'Chalkboard SE', cursive;*/
|
|
17
|
-
/*--rgb-accent: 255, 105, 180;*/
|
|
18
|
-
/*--rgb-color: 102, 51, 153;*/
|
|
19
|
-
/*--rgb-input: 255, 235, 235;*/
|
|
20
|
-
/*--shadow: 5px 5px 15px -8px rebeccapurple;*/
|
|
21
|
-
|
|
22
|
-
/*height: 50vh;*/
|
|
23
|
-
/*min-height: 400px;*/
|
|
24
|
-
/*max-height: 800px;*/
|
|
4
|
+
[data-theme='dark'] em-emoji-picker {
|
|
5
|
+
/* TODO(burdon): Use tailwind tokens. */
|
|
6
|
+
--background-rgb: #3b3b3f;
|
|
7
|
+
--rgb-background: #3b3b3f;
|
|
8
|
+
--font-family: 'Inter Variable', ui-sans-serif;
|
|
25
9
|
}
|
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React, { useState } from 'react';
|
|
9
7
|
|
|
10
8
|
import { Toolbar } from '@dxos/react-ui';
|
|
11
|
-
import { withLayout, withTheme } from '@dxos/
|
|
9
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
10
|
|
|
13
11
|
import { HuePicker, type HuePickerProps } from './HuePicker';
|
|
14
12
|
|
|
15
|
-
const
|
|
13
|
+
const DefaultStory = (props: HuePickerProps) => {
|
|
16
14
|
const [hue, setHue] = useState<string | undefined>(props.defaultValue);
|
|
17
15
|
|
|
18
16
|
return (
|
|
@@ -28,18 +26,18 @@ const ToolbarStory = (props: HuePickerProps) => {
|
|
|
28
26
|
);
|
|
29
27
|
};
|
|
30
28
|
|
|
31
|
-
const meta
|
|
29
|
+
const meta = {
|
|
32
30
|
title: 'ui/react-ui-pickers/HuePicker',
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
};
|
|
31
|
+
component: HuePicker,
|
|
32
|
+
render: DefaultStory,
|
|
33
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
34
|
+
} satisfies Meta<typeof HuePicker>;
|
|
38
35
|
|
|
39
36
|
export default meta;
|
|
40
37
|
|
|
41
|
-
|
|
42
|
-
|
|
38
|
+
type Story = StoryObj<typeof meta>;
|
|
39
|
+
|
|
40
|
+
export const Default: Story = {
|
|
43
41
|
args: {
|
|
44
42
|
defaultValue: 'red',
|
|
45
43
|
},
|
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
|
-
import { type ButtonProps, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
8
|
-
import { hues } from '@dxos/
|
|
7
|
+
import { type ButtonProps, type IconProps, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { getSize, hues, osTranslations } from '@dxos/ui-theme';
|
|
9
9
|
|
|
10
10
|
import { PickerButton, type PickerButtonProps } from '../PickerButton';
|
|
11
11
|
|
|
@@ -18,12 +18,12 @@ export type HuePickerProps = {
|
|
|
18
18
|
} & Pick<PickerButtonProps, 'disabled' | 'defaultValue' | 'value' | 'onChange' | 'onReset' | 'rootVariant'>;
|
|
19
19
|
|
|
20
20
|
export const HuePicker = (props: ThemedClassName<HuePickerProps>) => {
|
|
21
|
-
const { t } = useTranslation(
|
|
21
|
+
const { t } = useTranslation(osTranslations);
|
|
22
22
|
|
|
23
23
|
return (
|
|
24
24
|
<PickerButton
|
|
25
25
|
Component={HuePreview}
|
|
26
|
-
label={t('select
|
|
26
|
+
label={t('select-hue.label')}
|
|
27
27
|
icon='ph--palette--regular'
|
|
28
28
|
values={hues}
|
|
29
29
|
{...props}
|
|
@@ -31,15 +31,11 @@ export const HuePicker = (props: ThemedClassName<HuePickerProps>) => {
|
|
|
31
31
|
);
|
|
32
32
|
};
|
|
33
33
|
|
|
34
|
-
const HuePreview = ({ value }: { value: string }) => {
|
|
35
|
-
const size = 16;
|
|
34
|
+
const HuePreview = ({ value, size = 5 }: { value: string; size?: IconProps['size'] }) => {
|
|
36
35
|
return (
|
|
37
|
-
<div className='flex
|
|
38
|
-
<svg
|
|
39
|
-
|
|
40
|
-
className='is-[var(--hue-preview-size,1rem)] bs-[var(--hue-preview-size,1rem)]'
|
|
41
|
-
>
|
|
42
|
-
<rect x={0} y={0} width={size} height={size} fill={`var(--dx-${value}Fill)`} strokeWidth={4} />
|
|
36
|
+
<div role='none' className='flex justify-center items-center'>
|
|
37
|
+
<svg viewBox={`0 0 ${size} ${size}`} className={getSize(size)}>
|
|
38
|
+
<rect x={0} y={0} width={size} height={size} fill={`var(--color-${value}-surface)`} strokeWidth={4} />
|
|
43
39
|
</svg>
|
|
44
40
|
</div>
|
|
45
41
|
);
|
|
@@ -2,17 +2,15 @@
|
|
|
2
2
|
// Copyright 2025 DXOS.org
|
|
3
3
|
//
|
|
4
4
|
|
|
5
|
-
import '@dxos-theme';
|
|
6
|
-
|
|
7
5
|
import { type Meta, type StoryObj } from '@storybook/react-vite';
|
|
8
6
|
import React, { useState } from 'react';
|
|
9
7
|
|
|
10
8
|
import { Toolbar } from '@dxos/react-ui';
|
|
11
|
-
import { withLayout, withTheme } from '@dxos/
|
|
9
|
+
import { withLayout, withTheme } from '@dxos/react-ui/testing';
|
|
12
10
|
|
|
13
11
|
import { IconPicker, type IconPickerProps } from './IconPicker';
|
|
14
12
|
|
|
15
|
-
const
|
|
13
|
+
const DefaultStory = (props: IconPickerProps) => {
|
|
16
14
|
const [icon, setIcon] = useState<string | undefined>(props.value ?? props.defaultValue);
|
|
17
15
|
console.log(icon);
|
|
18
16
|
|
|
@@ -23,17 +21,17 @@ const ToolbarStory = (props: IconPickerProps) => {
|
|
|
23
21
|
);
|
|
24
22
|
};
|
|
25
23
|
|
|
26
|
-
const meta
|
|
24
|
+
const meta = {
|
|
27
25
|
title: 'ui/react-ui-pickers/IconPicker',
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
};
|
|
26
|
+
component: IconPicker,
|
|
27
|
+
render: DefaultStory,
|
|
28
|
+
decorators: [withTheme(), withLayout({ layout: 'column' })],
|
|
29
|
+
} satisfies Meta<typeof IconPicker>;
|
|
33
30
|
|
|
34
31
|
export default meta;
|
|
35
32
|
|
|
36
|
-
|
|
37
|
-
|
|
33
|
+
type Story = StoryObj<typeof meta>;
|
|
34
|
+
|
|
35
|
+
export const Default: Story = {
|
|
38
36
|
args: {},
|
|
39
37
|
};
|
|
@@ -5,9 +5,12 @@
|
|
|
5
5
|
import React from 'react';
|
|
6
6
|
|
|
7
7
|
import { type ButtonProps, Icon, type IconProps, type ThemedClassName, useTranslation } from '@dxos/react-ui';
|
|
8
|
+
import { osTranslations } from '@dxos/ui-theme';
|
|
8
9
|
|
|
9
10
|
import { PickerButton, type PickerButtonProps } from '../PickerButton';
|
|
10
11
|
|
|
12
|
+
import { iconValues } from './icons';
|
|
13
|
+
|
|
11
14
|
export type IconPickerProps = {
|
|
12
15
|
disabled?: boolean;
|
|
13
16
|
defaultValue?: string;
|
|
@@ -16,16 +19,16 @@ export type IconPickerProps = {
|
|
|
16
19
|
onReset?: ButtonProps['onClick'];
|
|
17
20
|
} & Pick<
|
|
18
21
|
PickerButtonProps,
|
|
19
|
-
'disabled' | '
|
|
22
|
+
'disabled' | 'rootVariant' | 'iconSize' | 'defaultValue' | 'value' | 'onChange' | 'onReset'
|
|
20
23
|
>;
|
|
21
24
|
|
|
22
25
|
export const IconPicker = ({ ...props }: ThemedClassName<IconPickerProps>) => {
|
|
23
|
-
const { t } = useTranslation(
|
|
26
|
+
const { t } = useTranslation(osTranslations);
|
|
24
27
|
|
|
25
28
|
return (
|
|
26
29
|
<PickerButton
|
|
27
30
|
Component={IconPreview}
|
|
28
|
-
label={t('select
|
|
31
|
+
label={t('select-icon.label')}
|
|
29
32
|
icon='ph--selection--regular'
|
|
30
33
|
values={iconValues}
|
|
31
34
|
{...props}
|
|
@@ -33,63 +36,6 @@ export const IconPicker = ({ ...props }: ThemedClassName<IconPickerProps>) => {
|
|
|
33
36
|
);
|
|
34
37
|
};
|
|
35
38
|
|
|
36
|
-
const IconPreview = ({ value,
|
|
37
|
-
return <Icon icon={`ph--${value}--regular`} size={
|
|
39
|
+
const IconPreview = ({ value, size }: { value: string; size?: IconProps['size'] }) => {
|
|
40
|
+
return <Icon icon={`ph--${value}--regular`} size={size} />;
|
|
38
41
|
};
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* https://phosphoricons.com
|
|
42
|
-
* NOTE: Select icons that we are unlikely to use for the UI.
|
|
43
|
-
*/
|
|
44
|
-
const icons = [
|
|
45
|
-
'ph--air-traffic-control--regular',
|
|
46
|
-
'ph--asterisk--regular',
|
|
47
|
-
'ph--atom--regular',
|
|
48
|
-
'ph--basketball--regular',
|
|
49
|
-
'ph--butterfly--regular',
|
|
50
|
-
'ph--cactus--regular',
|
|
51
|
-
'ph--cake--regular',
|
|
52
|
-
'ph--calendar-dots--regular',
|
|
53
|
-
'ph--campfire--regular',
|
|
54
|
-
'ph--command--regular',
|
|
55
|
-
'ph--confetti--regular',
|
|
56
|
-
'ph--detective--regular',
|
|
57
|
-
'ph--disco-ball--regular',
|
|
58
|
-
'ph--dna--regular',
|
|
59
|
-
'ph--factory--regular',
|
|
60
|
-
'ph--flag-banner-fold--regular',
|
|
61
|
-
'ph--flask--regular',
|
|
62
|
-
'ph--flower-lotus--regular',
|
|
63
|
-
'ph--flying-saucer--regular',
|
|
64
|
-
'ph--game-controller--regular',
|
|
65
|
-
'ph--gavel--regular',
|
|
66
|
-
'ph--gift--regular',
|
|
67
|
-
'ph--guitar--regular',
|
|
68
|
-
'ph--hamburger--regular',
|
|
69
|
-
'ph--handshake--regular',
|
|
70
|
-
'ph--heart--regular',
|
|
71
|
-
'ph--lightbulb--regular',
|
|
72
|
-
'ph--lock--regular',
|
|
73
|
-
'ph--martini--regular',
|
|
74
|
-
'ph--medal-military--regular',
|
|
75
|
-
'ph--moped-front--regular',
|
|
76
|
-
'ph--office-chair--regular',
|
|
77
|
-
'ph--paint-brush-household--regular',
|
|
78
|
-
'ph--peace--regular',
|
|
79
|
-
'ph--person-simple-hike--regular',
|
|
80
|
-
'ph--piggy-bank--regular',
|
|
81
|
-
'ph--potted-plant--regular',
|
|
82
|
-
'ph--radioactive--regular',
|
|
83
|
-
'ph--rocket-launch--regular',
|
|
84
|
-
'ph--shield-star--regular',
|
|
85
|
-
'ph--shopping-cart--regular',
|
|
86
|
-
'ph--stethoscope--regular',
|
|
87
|
-
'ph--student--regular',
|
|
88
|
-
'ph--sun--regular',
|
|
89
|
-
'ph--tote--regular',
|
|
90
|
-
'ph--tree--regular',
|
|
91
|
-
'ph--users-three--regular',
|
|
92
|
-
'ph--yin-yang--regular',
|
|
93
|
-
];
|
|
94
|
-
|
|
95
|
-
const iconValues = icons.map((icon) => icon.match(/ph--(.+)--regular/)?.[1] ?? icon);
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
//
|
|
2
|
+
// Copyright 2025 DXOS.org
|
|
3
|
+
//
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* https://phosphoricons.com
|
|
7
|
+
* NOTE: Select icons that we are unlikely to use for the UI.
|
|
8
|
+
*/
|
|
9
|
+
export const icons = [
|
|
10
|
+
'ph--house-line--regular',
|
|
11
|
+
'ph--planet--regular',
|
|
12
|
+
'ph--castle-turret--regular',
|
|
13
|
+
'ph--snowflake--regular',
|
|
14
|
+
'ph--virus--regular',
|
|
15
|
+
'ph--graph--regular',
|
|
16
|
+
'ph--air-traffic-control--regular',
|
|
17
|
+
'ph--asterisk--regular',
|
|
18
|
+
'ph--atom--regular',
|
|
19
|
+
'ph--basketball--regular',
|
|
20
|
+
'ph--butterfly--regular',
|
|
21
|
+
'ph--cactus--regular',
|
|
22
|
+
'ph--cake--regular',
|
|
23
|
+
'ph--calendar-dots--regular',
|
|
24
|
+
'ph--campfire--regular',
|
|
25
|
+
'ph--command--regular',
|
|
26
|
+
'ph--confetti--regular',
|
|
27
|
+
'ph--detective--regular',
|
|
28
|
+
'ph--disco-ball--regular',
|
|
29
|
+
'ph--dna--regular',
|
|
30
|
+
'ph--factory--regular',
|
|
31
|
+
'ph--flag-banner-fold--regular',
|
|
32
|
+
'ph--flask--regular',
|
|
33
|
+
'ph--flower-lotus--regular',
|
|
34
|
+
'ph--flying-saucer--regular',
|
|
35
|
+
'ph--game-controller--regular',
|
|
36
|
+
'ph--gavel--regular',
|
|
37
|
+
'ph--gift--regular',
|
|
38
|
+
'ph--guitar--regular',
|
|
39
|
+
'ph--hamburger--regular',
|
|
40
|
+
'ph--handshake--regular',
|
|
41
|
+
'ph--heart--regular',
|
|
42
|
+
'ph--lightbulb--regular',
|
|
43
|
+
'ph--lock--regular',
|
|
44
|
+
'ph--martini--regular',
|
|
45
|
+
'ph--medal-military--regular',
|
|
46
|
+
'ph--moped-front--regular',
|
|
47
|
+
'ph--office-chair--regular',
|
|
48
|
+
'ph--paint-brush-household--regular',
|
|
49
|
+
'ph--peace--regular',
|
|
50
|
+
'ph--person-simple-hike--regular',
|
|
51
|
+
'ph--piggy-bank--regular',
|
|
52
|
+
'ph--potted-plant--regular',
|
|
53
|
+
'ph--radioactive--regular',
|
|
54
|
+
'ph--rocket-launch--regular',
|
|
55
|
+
'ph--shield-star--regular',
|
|
56
|
+
'ph--shopping-cart--regular',
|
|
57
|
+
'ph--stethoscope--regular',
|
|
58
|
+
'ph--student--regular',
|
|
59
|
+
'ph--sun--regular',
|
|
60
|
+
'ph--tote--regular',
|
|
61
|
+
'ph--tree--regular',
|
|
62
|
+
'ph--users-three--regular',
|
|
63
|
+
'ph--yin-yang--regular',
|
|
64
|
+
];
|
|
65
|
+
|
|
66
|
+
export const iconValues = icons.map((icon) => icon.match(/ph--(.+)--regular/)?.[1] ?? icon);
|
|
@@ -8,10 +8,10 @@ import React, { type FC, useEffect, useState } from 'react';
|
|
|
8
8
|
import { Button, DropdownMenu, Icon, type IconProps, type ThemedClassName, Toolbar, Tooltip } from '@dxos/react-ui';
|
|
9
9
|
|
|
10
10
|
export type PickerButtonProps = ThemedClassName<{
|
|
11
|
-
Component: FC<{ value: string;
|
|
11
|
+
Component: FC<{ value: string; size?: IconProps['size'] }>;
|
|
12
12
|
label: string;
|
|
13
13
|
icon: string;
|
|
14
|
-
values: string[];
|
|
14
|
+
values: readonly string[];
|
|
15
15
|
disabled?: boolean;
|
|
16
16
|
defaultValue?: string;
|
|
17
17
|
value?: string;
|
|
@@ -25,8 +25,8 @@ export const PickerButton = ({
|
|
|
25
25
|
Component,
|
|
26
26
|
disabled,
|
|
27
27
|
classNames,
|
|
28
|
-
defaultValue:
|
|
29
|
-
value:
|
|
28
|
+
defaultValue: defaultValueProp,
|
|
29
|
+
value: valueProp,
|
|
30
30
|
values,
|
|
31
31
|
label,
|
|
32
32
|
icon,
|
|
@@ -36,30 +36,29 @@ export const PickerButton = ({
|
|
|
36
36
|
iconSize = 5,
|
|
37
37
|
}: PickerButtonProps) => {
|
|
38
38
|
const [value, setValue] = useControllableState<string>({
|
|
39
|
-
prop:
|
|
40
|
-
defaultProp:
|
|
39
|
+
prop: valueProp,
|
|
40
|
+
defaultProp: defaultValueProp,
|
|
41
41
|
onChange,
|
|
42
42
|
});
|
|
43
43
|
// TODO(burdon): useControllableState doesn't update the prop when the value is changed. Replace it.
|
|
44
|
-
useEffect(() => setValue(
|
|
44
|
+
useEffect(() => setValue(valueProp), [valueProp]);
|
|
45
45
|
|
|
46
46
|
const [open, setOpen] = useState<boolean>(false);
|
|
47
|
-
|
|
48
47
|
const TriggerRoot = rootVariant === 'toolbar-button' ? Toolbar.Button : Button;
|
|
49
48
|
|
|
50
49
|
return (
|
|
51
50
|
<DropdownMenu.Root modal={false} open={open} onOpenChange={setOpen}>
|
|
52
51
|
<Tooltip.Trigger asChild content={label} side='bottom'>
|
|
53
52
|
<DropdownMenu.Trigger asChild>
|
|
54
|
-
<TriggerRoot classNames={['gap-2
|
|
53
|
+
<TriggerRoot classNames={['gap-2 py-1', classNames]} disabled={disabled}>
|
|
55
54
|
<span className='sr-only'>{label}</span>
|
|
56
|
-
{(value && <Component value={value}
|
|
55
|
+
{(value && <Component value={value} size={iconSize} />) || <Icon icon={icon} size={iconSize} />}
|
|
57
56
|
<Icon icon='ph--caret-down--bold' size={3} />
|
|
58
57
|
</TriggerRoot>
|
|
59
58
|
</DropdownMenu.Trigger>
|
|
60
59
|
</Tooltip.Trigger>
|
|
61
60
|
<DropdownMenu.Portal>
|
|
62
|
-
<DropdownMenu.Content side='bottom' classNames='!
|
|
61
|
+
<DropdownMenu.Content side='bottom' classNames='!w-min'>
|
|
63
62
|
<DropdownMenu.Viewport classNames='grid grid-cols-[repeat(6,min-content)]'>
|
|
64
63
|
{values.map((_value) => {
|
|
65
64
|
return (
|
|
@@ -69,7 +68,7 @@ export const PickerButton = ({
|
|
|
69
68
|
onCheckedChange={() => setValue(_value)}
|
|
70
69
|
classNames={'p-1 items-center justify-center aspect-square'}
|
|
71
70
|
>
|
|
72
|
-
<Component value={_value}
|
|
71
|
+
<Component value={_value} size={iconSize} />
|
|
73
72
|
</DropdownMenu.CheckboxItem>
|
|
74
73
|
);
|
|
75
74
|
})}
|