@mirohq/design-system-chip 1.2.62 → 1.3.0-filter-chip.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/dist/main.js CHANGED
@@ -3,61 +3,306 @@
3
3
  var jsxRuntime = require('react/jsx-runtime');
4
4
  var React = require('react');
5
5
  var designSystemIcons = require('@mirohq/design-system-icons');
6
+ var designSystemSpinner = require('@mirohq/design-system-spinner');
6
7
  var designSystemStitches = require('@mirohq/design-system-stitches');
7
8
  var designSystemPrimitive = require('@mirohq/design-system-primitive');
8
9
  var designSystemBaseButton = require('@mirohq/design-system-base-button');
9
10
  var designSystemStyles = require('@mirohq/design-system-styles');
10
11
 
11
- const StyledChip = designSystemStitches.styled(designSystemPrimitive.Primitive.div, {
12
- fontSize: "$150",
13
- lineHeight: 1.3,
14
- padding: "$50 $100",
12
+ const StyledImageSlot = designSystemStitches.styled(designSystemPrimitive.Primitive.span, {
13
+ display: "inline-flex",
14
+ alignItems: "center",
15
+ justifyContent: "center",
16
+ flexShrink: 0,
17
+ verticalAlign: "middle",
18
+ paddingInline: "$50",
19
+ "& img": {
20
+ display: "block",
21
+ square: 16,
22
+ borderRadius: "$round",
23
+ objectFit: "cover"
24
+ }
25
+ });
26
+
27
+ const LABEL_OFFSET = 2;
28
+ const imageSlotImg = (size) => ({
29
+ ["& ".concat(StyledImageSlot, " img")]: {
30
+ square: size
31
+ }
32
+ });
33
+ const chipLayout = {
15
34
  borderRadius: "$round",
16
35
  display: "inline-flex",
17
36
  alignItems: "center",
18
- gap: "$50",
19
- backgroundColor: "$chip-background",
20
- color: "$chip-text",
37
+ width: "fit-content",
21
38
  maxWidth: "100%",
39
+ flexShrink: 0,
40
+ boxSizing: "border-box",
41
+ border: "1px solid transparent",
42
+ lineHeight: 1.3,
43
+ // Chip labels are regular. Pressable uses BaseButton; don't keep Button's
44
+ // semibold from that shell.
45
+ fontWeight: "$regular"
46
+ };
47
+ const chipSizes = {
48
+ "x-large": {
49
+ height: "$12",
50
+ fontSize: "$200",
51
+ paddingX: "calc($200 + ".concat(LABEL_OFFSET, "px)"),
52
+ ...imageSlotImg("$8")
53
+ },
54
+ large: {
55
+ height: "$10",
56
+ fontSize: "$200",
57
+ paddingX: "calc($150 + ".concat(LABEL_OFFSET, "px)"),
58
+ ...imageSlotImg("$6")
59
+ },
60
+ medium: {
61
+ height: "$8",
62
+ fontSize: "$175",
63
+ paddingX: "calc($100 + ".concat(LABEL_OFFSET, "px)"),
64
+ ...imageSlotImg("$5")
65
+ },
66
+ small: {
67
+ height: "$6",
68
+ fontSize: "$175",
69
+ paddingX: "calc($100 + ".concat(LABEL_OFFSET, "px)"),
70
+ ...imageSlotImg("$4")
71
+ }
72
+ };
73
+ const defaultIdle = {
74
+ color: "$chip-text-on-default",
75
+ backgroundColor: "$chip-background-default",
76
+ borderColor: "$chip-border-default"
77
+ };
78
+ const outlineIdle = {
79
+ color: "$chip-text-on-outline",
80
+ backgroundColor: "$transparent",
81
+ borderColor: "$chip-border-outline"
82
+ };
83
+ const defaultInteractive = {
84
+ ...defaultIdle,
85
+ _hover: {
86
+ color: "$chip-text-on-default",
87
+ backgroundColor: "$chip-background-default-hover",
88
+ borderColor: "$chip-border-default-hover"
89
+ },
90
+ "&[data-pressed]": {
91
+ color: "$chip-text-on-default",
92
+ backgroundColor: "$chip-background-default-pressed",
93
+ borderColor: "$chip-border-default"
94
+ },
95
+ // Attribute selector so `disabled` reaches BaseButton / usePress.
96
+ "&[disabled]": {
97
+ backgroundColor: "$background-disabled",
98
+ color: "$text-on-disabled"
99
+ }
100
+ };
101
+ const outlineInteractive = {
102
+ ...outlineIdle,
103
+ _hover: {
104
+ backgroundColor: "$chip-background-outline-hover",
105
+ borderColor: "$chip-border-outline-hover",
106
+ color: "$chip-text-on-outline"
107
+ },
108
+ "&[data-pressed]": {
109
+ backgroundColor: "$chip-background-outline-pressed",
110
+ borderColor: "$chip-border-outline-pressed",
111
+ color: "$chip-text-on-outline"
112
+ },
113
+ "&[disabled]": {
114
+ backgroundColor: "$transparent",
115
+ borderColor: "$border-disabled",
116
+ color: "$text-disabled"
117
+ }
118
+ };
119
+ const StyledChip = designSystemStitches.styled(designSystemPrimitive.Primitive.div, {
120
+ ...chipLayout,
22
121
  variants: {
122
+ variant: {
123
+ default: defaultIdle,
124
+ outline: outlineIdle
125
+ },
23
126
  disabled: {
24
- true: {
25
- backgroundColor: "$chip-background-disabled"
127
+ true: {}
128
+ },
129
+ size: chipSizes
130
+ },
131
+ compoundVariants: [
132
+ {
133
+ variant: "default",
134
+ disabled: true,
135
+ css: {
136
+ backgroundColor: "$background-disabled",
137
+ color: "$text-on-disabled",
138
+ "& button": {
139
+ color: "$icon-on-disabled"
140
+ }
141
+ }
142
+ },
143
+ {
144
+ variant: "outline",
145
+ disabled: true,
146
+ css: {
147
+ backgroundColor: "$transparent",
148
+ borderColor: "$border-disabled",
149
+ color: "$text-disabled",
150
+ "& button": {
151
+ color: "$icon-disabled"
152
+ }
26
153
  }
27
154
  }
155
+ ],
156
+ defaultVariants: {
157
+ variant: "default",
158
+ size: "medium"
159
+ }
160
+ });
161
+ const StyledPressableChip = designSystemStitches.styled(designSystemBaseButton.BaseButton, {
162
+ ...chipLayout,
163
+ position: "relative",
164
+ ...designSystemStyles.focus.css({
165
+ boxShadow: "$focus"
166
+ }),
167
+ // Loading stays visually idle — only the wait cursor signals it. Don't reuse
168
+ // the disabled mute; that made loading look broken.
169
+ '&[aria-busy="true"]': {
170
+ cursor: "wait",
171
+ pointerEvents: "none"
172
+ },
173
+ variants: {
174
+ variant: {
175
+ default: defaultInteractive,
176
+ outline: outlineInteractive
177
+ },
178
+ size: chipSizes
179
+ },
180
+ defaultVariants: {
181
+ variant: "default",
182
+ size: "medium"
28
183
  }
29
184
  });
30
185
  const StyledChipContent = designSystemStitches.styled(designSystemPrimitive.Primitive.div, {
31
186
  overflow: "hidden",
32
187
  whiteSpace: "nowrap",
33
- textOverflow: "ellipsis"
188
+ textOverflow: "ellipsis",
189
+ // Taller than the em box so descenders (g, y) aren't clipped by overflow.
190
+ lineHeight: 1.3,
191
+ minWidth: 0,
192
+ display: "flex",
193
+ alignItems: "center",
194
+ variants: {
195
+ loading: {
196
+ true: {
197
+ opacity: 0
198
+ }
199
+ }
200
+ }
201
+ });
202
+ const StyledSpinnerBox = designSystemStitches.styled(designSystemPrimitive.Primitive.div, {
203
+ display: "flex",
204
+ alignItems: "center",
205
+ justifyContent: "center",
206
+ position: "absolute",
207
+ top: 0,
208
+ left: 0,
209
+ bottom: 0,
210
+ right: 0,
211
+ margin: "auto",
212
+ zIndex: 1
34
213
  });
35
214
  const StyledChipButton = designSystemStitches.styled(designSystemBaseButton.BaseButton, {
215
+ // Figma Chip: spacing-100 before the close glyph, not container gap.
216
+ paddingInlineStart: "$100",
217
+ flexShrink: 0,
36
218
  color: "$icon-secondary",
37
219
  ...designSystemStyles.focus.css({
38
220
  boxShadow: "$focus"
39
221
  })
40
222
  });
41
223
 
42
- const StyledImageSlot = designSystemStitches.styled(designSystemPrimitive.Primitive.span, {
43
- paddingInline: "$50"
44
- });
45
-
46
224
  const ImageSlot = StyledImageSlot;
47
225
 
226
+ const hasPressEvent = (props) => {
227
+ if ("onClick" in props && props.onClick != null) return true;
228
+ if ("onPress" in props && props.onPress != null) return true;
229
+ return false;
230
+ };
48
231
  const Chip = React.forwardRef(
49
- ({ children, removable = true, onRemove, removeAriaLabel, ...restProps }, forwardRef) => /* @__PURE__ */ jsxRuntime.jsxs(StyledChip, { ...restProps, ref: forwardRef, children: [
50
- /* @__PURE__ */ jsxRuntime.jsx(StyledChipContent, { children }),
51
- removable && /* @__PURE__ */ jsxRuntime.jsx(
52
- StyledChipButton,
232
+ (props, forwardRef) => {
233
+ const {
234
+ children,
235
+ removable = true,
236
+ onRemove,
237
+ removeAriaLabel,
238
+ loading = false,
239
+ size = "medium",
240
+ variant = "default",
241
+ disabled,
242
+ ...restProps
243
+ } = props;
244
+ const pressable = hasPressEvent(restProps);
245
+ const isLoading = pressable && loading;
246
+ let spinnerSize = "medium";
247
+ if (typeof size === "string" && ["small", "medium"].includes(size)) {
248
+ spinnerSize = "small";
249
+ }
250
+ const content = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
251
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(
252
+ StyledSpinnerBox,
253
+ {
254
+ "aria-hidden": true,
255
+ "data-testid": process.env.NODE_ENV === "test" ? "chip-spinner" : void 0,
256
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystemSpinner.Spinner, { size: spinnerSize })
257
+ }
258
+ ),
259
+ /* @__PURE__ */ jsxRuntime.jsx(
260
+ StyledChipContent,
261
+ {
262
+ "data-chip-content": "",
263
+ loading: isLoading || void 0,
264
+ children
265
+ }
266
+ ),
267
+ !pressable && removable && /* @__PURE__ */ jsxRuntime.jsx(
268
+ StyledChipButton,
269
+ {
270
+ type: "button",
271
+ disabled: disabled === true || void 0,
272
+ onClick: onRemove,
273
+ "aria-label": removeAriaLabel,
274
+ children: /* @__PURE__ */ jsxRuntime.jsx(designSystemIcons.IconCross, { size: "small" })
275
+ }
276
+ )
277
+ ] });
278
+ if (pressable) {
279
+ return /* @__PURE__ */ jsxRuntime.jsx(
280
+ StyledPressableChip,
281
+ {
282
+ type: "button",
283
+ ...restProps,
284
+ size,
285
+ variant,
286
+ disabled: disabled === true || void 0,
287
+ ref: forwardRef,
288
+ "aria-busy": isLoading || void 0,
289
+ "aria-disabled": isLoading || void 0,
290
+ children: content
291
+ }
292
+ );
293
+ }
294
+ return /* @__PURE__ */ jsxRuntime.jsx(
295
+ StyledChip,
53
296
  {
54
- type: "button",
55
- onClick: onRemove,
56
- "aria-label": removeAriaLabel,
57
- children: /* @__PURE__ */ jsxRuntime.jsx(designSystemIcons.IconCross, { size: "small" })
297
+ ...restProps,
298
+ size,
299
+ variant,
300
+ disabled,
301
+ ref: forwardRef,
302
+ children: content
58
303
  }
59
- )
60
- ] })
304
+ );
305
+ }
61
306
  );
62
307
  Chip.ImageSlot = ImageSlot;
63
308
 
package/dist/main.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"main.js","sources":["../src/chip.styled.tsx","../src/partials/image-icon.styled.tsx","../src/partials/image-slot.tsx","../src/chip.tsx"],"sourcesContent":["import { styled } from '@mirohq/design-system-stitches'\nimport type { StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\nimport { BaseButton } from '@mirohq/design-system-base-button'\nimport { focus } from '@mirohq/design-system-styles'\n\nexport const StyledChip = styled(Primitive.div, {\n fontSize: '$150',\n lineHeight: 1.3,\n padding: '$50 $100',\n borderRadius: '$round',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '$50',\n backgroundColor: '$chip-background',\n color: '$chip-text',\n maxWidth: '100%',\n variants: {\n disabled: {\n true: {\n backgroundColor: '$chip-background-disabled',\n },\n },\n },\n})\n\nexport const StyledChipContent = styled(Primitive.div, {\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n})\n\nexport const StyledChipButton = styled(BaseButton, {\n color: '$icon-secondary',\n ...focus.css({\n boxShadow: '$focus',\n }),\n})\n\nexport type StyledChipProps = StrictComponentProps<typeof StyledChip>\n","import type { StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { styled } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\n\nexport const StyledImageSlot = styled(Primitive.span, {\n paddingInline: '$50',\n})\n\nexport type StyledImageSlotProps = StrictComponentProps<typeof StyledImageSlot>\n","import type { StyledImageSlotProps } from './image-icon.styled'\nimport { StyledImageSlot } from './image-icon.styled'\n\nexport interface ImageSlotProps extends StyledImageSlotProps {}\n\nexport const ImageSlot = StyledImageSlot\n","import React from 'react'\nimport type { ElementRef, ForwardRefExoticComponent } from 'react'\nimport { IconCross } from '@mirohq/design-system-icons'\n\nimport { StyledChip, StyledChipButton, StyledChipContent } from './chip.styled'\nimport type { StyledChipProps } from './chip.styled'\nimport { ImageSlot } from './partials/image-slot'\n\ninterface RemovableProps {\n /**\n * Event handler called when the chip's remove button is clicked.\n */\n onRemove: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void\n\n /**\n * Remove button label to make the button recognizable by the screen readers.\n */\n removeAriaLabel: string\n}\n\nexport type ChipProps = (StyledChipProps & {\n /**\n * Show a button to remove the Chip\n * @default true\n */\n removable?: boolean\n}) &\n (\n | RemovableProps\n | { removable: false; removeAriaLabel?: never; onRemove?: never }\n )\n\nexport const Chip = React.forwardRef<ElementRef<typeof StyledChip>, ChipProps>(\n (\n { children, removable = true, onRemove, removeAriaLabel, ...restProps },\n forwardRef\n ) => (\n <StyledChip {...restProps} ref={forwardRef}>\n <StyledChipContent>{children}</StyledChipContent>\n {removable && (\n <StyledChipButton\n type='button'\n onClick={onRemove}\n aria-label={removeAriaLabel}\n >\n <IconCross size='small' />\n </StyledChipButton>\n )}\n </StyledChip>\n )\n) as ForwardRefExoticComponent<ChipProps> & Partials\n\nexport interface Partials {\n ImageSlot: typeof ImageSlot\n}\n\nChip.ImageSlot = ImageSlot\n"],"names":["styled","Primitive","BaseButton","focus","jsxs","jsx","IconCross"],"mappings":";;;;;;;;;;AAMO,MAAM,UAAA,GAAaA,2BAAA,CAAOC,+BAAA,CAAU,GAAA,EAAK;AAAA,EAC9C,QAAA,EAAU,MAAA;AAAA,EACV,UAAA,EAAY,GAAA;AAAA,EACZ,OAAA,EAAS,UAAA;AAAA,EACT,YAAA,EAAc,QAAA;AAAA,EACd,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,GAAA,EAAK,KAAA;AAAA,EACL,eAAA,EAAiB,kBAAA;AAAA,EACjB,KAAA,EAAO,YAAA;AAAA,EACP,QAAA,EAAU,MAAA;AAAA,EACV,QAAA,EAAU;AAAA,IACR,QAAA,EAAU;AAAA,MACR,IAAA,EAAM;AAAA,QACJ,eAAA,EAAiB;AAAA;AACnB;AACF;AAEJ,CAAC,CAAA;AAEM,MAAM,iBAAA,GAAoBD,2BAAA,CAAOC,+BAAA,CAAU,GAAA,EAAK;AAAA,EACrD,QAAA,EAAU,QAAA;AAAA,EACV,UAAA,EAAY,QAAA;AAAA,EACZ,YAAA,EAAc;AAChB,CAAC,CAAA;AAEM,MAAM,gBAAA,GAAmBD,4BAAOE,iCAAA,EAAY;AAAA,EACjD,KAAA,EAAO,iBAAA;AAAA,EACP,GAAGC,yBAAM,GAAA,CAAI;AAAA,IACX,SAAA,EAAW;AAAA,GACZ;AACH,CAAC,CAAA;;ACjCM,MAAM,eAAA,GAAkBH,2BAAA,CAAOC,+BAAA,CAAU,IAAA,EAAM;AAAA,EACpD,aAAA,EAAe;AACjB,CAAC,CAAA;;ACDM,MAAM,SAAA,GAAY,eAAA;;AC2BlB,MAAM,OAAO,KAAA,CAAM,UAAA;AAAA,EACxB,CACE,EAAE,QAAA,EAAU,SAAA,GAAY,IAAA,EAAM,UAAU,eAAA,EAAiB,GAAG,SAAA,EAAU,EACtE,+BAEAG,eAAA,CAAC,UAAA,EAAA,EAAY,GAAG,SAAA,EAAW,KAAK,UAAA,EAC9B,QAAA,EAAA;AAAA,oBAAAC,cAAA,CAAC,qBAAmB,QAAA,EAAS,CAAA;AAAA,IAC5B,SAAA,oBACCA,cAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,QAAA;AAAA,QACT,YAAA,EAAY,eAAA;AAAA,QAEZ,QAAA,kBAAAA,cAAA,CAACC,2BAAA,EAAA,EAAU,IAAA,EAAK,OAAA,EAAQ;AAAA;AAAA;AAC1B,GAAA,EAEJ;AAEJ;AAMA,IAAA,CAAK,SAAA,GAAY,SAAA;;;;"}
1
+ {"version":3,"file":"main.js","sources":["../src/partials/image-icon.styled.tsx","../src/chip.styled.tsx","../src/partials/image-slot.tsx","../src/chip.tsx"],"sourcesContent":["import type { StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { styled } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\n\nexport const StyledImageSlot = styled(Primitive.span, {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n verticalAlign: 'middle',\n paddingInline: '$50',\n '& img': {\n display: 'block',\n square: 16,\n borderRadius: '$round',\n objectFit: 'cover',\n },\n})\n\nexport type StyledImageSlotProps = StrictComponentProps<typeof StyledImageSlot>\n","import { styled } from '@mirohq/design-system-stitches'\nimport type { CSS, StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\nimport { BaseButton } from '@mirohq/design-system-base-button'\nimport { focus } from '@mirohq/design-system-styles'\n\nimport { StyledImageSlot } from './partials/image-icon.styled'\n\n// Same offset Button uses so paddingX matches that scale without importing it.\nconst LABEL_OFFSET = 2\n\nconst imageSlotImg = (size: string): CSS => ({\n [`& ${StyledImageSlot} img`]: {\n square: size,\n },\n})\n\nconst chipLayout = {\n borderRadius: '$round',\n display: 'inline-flex',\n alignItems: 'center',\n width: 'fit-content',\n maxWidth: '100%',\n flexShrink: 0,\n boxSizing: 'border-box',\n border: '1px solid transparent',\n lineHeight: 1.3,\n // Chip labels are regular. Pressable uses BaseButton; don't keep Button's\n // semibold from that shell.\n fontWeight: '$regular',\n}\n\n// Copied from Button's size variant (same tokens and padding formula), not\n// imported — Chip owns this scale so Button can change independently.\nconst chipSizes = {\n 'x-large': {\n height: '$12',\n fontSize: '$200',\n paddingX: `calc($200 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$8'),\n },\n large: {\n height: '$10',\n fontSize: '$200',\n paddingX: `calc($150 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$6'),\n },\n medium: {\n height: '$8',\n fontSize: '$175',\n paddingX: `calc($100 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$5'),\n },\n small: {\n height: '$6',\n fontSize: '$175',\n paddingX: `calc($100 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$4'),\n },\n}\n\n// Hover and pressed only belong on the pressable shell.\nconst defaultIdle = {\n color: '$chip-text-on-default',\n backgroundColor: '$chip-background-default',\n borderColor: '$chip-border-default',\n}\n\nconst outlineIdle = {\n color: '$chip-text-on-outline',\n backgroundColor: '$transparent',\n borderColor: '$chip-border-outline',\n}\n\nconst defaultInteractive = {\n ...defaultIdle,\n _hover: {\n color: '$chip-text-on-default',\n backgroundColor: '$chip-background-default-hover',\n borderColor: '$chip-border-default-hover',\n },\n '&[data-pressed]': {\n color: '$chip-text-on-default',\n backgroundColor: '$chip-background-default-pressed',\n borderColor: '$chip-border-default',\n },\n // Attribute selector so `disabled` reaches BaseButton / usePress.\n '&[disabled]': {\n backgroundColor: '$background-disabled',\n color: '$text-on-disabled',\n },\n}\n\nconst outlineInteractive = {\n ...outlineIdle,\n _hover: {\n backgroundColor: '$chip-background-outline-hover',\n borderColor: '$chip-border-outline-hover',\n color: '$chip-text-on-outline',\n },\n '&[data-pressed]': {\n backgroundColor: '$chip-background-outline-pressed',\n borderColor: '$chip-border-outline-pressed',\n color: '$chip-text-on-outline',\n },\n '&[disabled]': {\n backgroundColor: '$transparent',\n borderColor: '$border-disabled',\n color: '$text-disabled',\n },\n}\n\nexport const StyledChip = styled(Primitive.div, {\n ...chipLayout,\n variants: {\n variant: {\n default: defaultIdle,\n outline: outlineIdle,\n },\n disabled: {\n true: {},\n },\n size: chipSizes,\n },\n compoundVariants: [\n {\n variant: 'default',\n disabled: true,\n css: {\n backgroundColor: '$background-disabled',\n color: '$text-on-disabled',\n '& button': {\n color: '$icon-on-disabled',\n },\n },\n },\n {\n variant: 'outline',\n disabled: true,\n css: {\n backgroundColor: '$transparent',\n borderColor: '$border-disabled',\n color: '$text-disabled',\n '& button': {\n color: '$icon-disabled',\n },\n },\n },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'medium',\n },\n})\n\nexport const StyledPressableChip = styled(BaseButton, {\n ...chipLayout,\n position: 'relative',\n ...focus.css({\n boxShadow: '$focus',\n }),\n // Loading stays visually idle — only the wait cursor signals it. Don't reuse\n // the disabled mute; that made loading look broken.\n '&[aria-busy=\"true\"]': {\n cursor: 'wait',\n pointerEvents: 'none',\n },\n variants: {\n variant: {\n default: defaultInteractive,\n outline: outlineInteractive,\n },\n size: chipSizes,\n },\n defaultVariants: {\n variant: 'default',\n size: 'medium',\n },\n})\n\nexport const StyledChipContent = styled(Primitive.div, {\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n // Taller than the em box so descenders (g, y) aren't clipped by overflow.\n lineHeight: 1.3,\n minWidth: 0,\n display: 'flex',\n alignItems: 'center',\n variants: {\n loading: {\n true: {\n opacity: 0,\n },\n },\n },\n})\n\nexport const StyledSpinnerBox = styled(Primitive.div, {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n position: 'absolute',\n top: 0,\n left: 0,\n bottom: 0,\n right: 0,\n margin: 'auto',\n zIndex: 1,\n})\n\nexport const StyledChipButton = styled(BaseButton, {\n // Figma Chip: spacing-100 before the close glyph, not container gap.\n paddingInlineStart: '$100',\n flexShrink: 0,\n color: '$icon-secondary',\n ...focus.css({\n boxShadow: '$focus',\n }),\n})\n\nexport type StyledChipProps = StrictComponentProps<typeof StyledChip>\n","import type { StyledImageSlotProps } from './image-icon.styled'\nimport { StyledImageSlot } from './image-icon.styled'\n\nexport interface ImageSlotProps extends StyledImageSlotProps {}\n\nexport const ImageSlot = StyledImageSlot\n","import React from 'react'\nimport type {\n ElementRef,\n ForwardRefExoticComponent,\n RefAttributes,\n} from 'react'\nimport type { BaseButtonProps } from '@mirohq/design-system-base-button'\nimport { IconCross } from '@mirohq/design-system-icons'\nimport { Spinner } from '@mirohq/design-system-spinner'\nimport type { SpinnerProps } from '@mirohq/design-system-spinner'\n\nimport {\n StyledChip,\n StyledChipButton,\n StyledChipContent,\n StyledPressableChip,\n StyledSpinnerBox,\n} from './chip.styled'\nimport type { StyledChipProps } from './chip.styled'\nimport { ImageSlot } from './partials/image-slot'\n\nexport type ChipProps = Omit<\n StyledChipProps,\n 'ref' | 'size' | 'variant' | 'disabled'\n> &\n Pick<BaseButtonProps, 'onPress'> &\n RefAttributes<HTMLDivElement | HTMLButtonElement> & {\n /**\n * Change the chip size. Same scale as Button (`small`, `medium`, `large`,\n * `x-large`).\n * @default 'medium'\n */\n size?: StyledChipProps['size']\n /**\n * Change the chip style. `default` is filled; `outline` is bordered.\n * @default 'default'\n */\n variant?: StyledChipProps['variant']\n /**\n * Disable the chip. When removable, the close control is disabled too.\n */\n disabled?: boolean\n /**\n * Show a button to remove the Chip\n * @default true\n */\n removable?: boolean\n /**\n * Show a spinner overlay and keep the chip non-interactive without the\n * disabled look. Pressable only.\n * @default false\n */\n loading?: boolean\n } & (\n | {\n /**\n * Event handler called when the chip's remove button is clicked.\n */\n onRemove: (\n event: React.MouseEvent<HTMLButtonElement, MouseEvent>\n ) => void\n /**\n * Remove button label to make the button recognizable by the screen readers.\n */\n removeAriaLabel: string\n }\n | { removable: false; removeAriaLabel?: never; onRemove?: never }\n )\n\nconst hasPressEvent = (props: object): boolean => {\n if ('onClick' in props && props.onClick != null) return true\n if ('onPress' in props && props.onPress != null) return true\n\n return false\n}\n\nexport const Chip = React.forwardRef<ElementRef<'div' | 'button'>, ChipProps>(\n (props, forwardRef) => {\n const {\n children,\n removable = true,\n onRemove,\n removeAriaLabel,\n loading = false,\n size = 'medium',\n variant = 'default',\n disabled,\n ...restProps\n } = props\n\n const pressable = hasPressEvent(restProps)\n const isLoading = pressable && loading\n\n let spinnerSize: SpinnerProps['size'] = 'medium'\n\n if (typeof size === 'string' && ['small', 'medium'].includes(size)) {\n spinnerSize = 'small'\n }\n\n const content = (\n <>\n {isLoading && (\n <StyledSpinnerBox\n aria-hidden\n data-testid={\n process.env.NODE_ENV === 'test' ? 'chip-spinner' : undefined\n }\n >\n <Spinner size={spinnerSize} />\n </StyledSpinnerBox>\n )}\n <StyledChipContent\n data-chip-content=''\n loading={isLoading || undefined}\n >\n {children}\n </StyledChipContent>\n {!pressable && removable && (\n <StyledChipButton\n type='button'\n disabled={disabled === true || undefined}\n onClick={onRemove}\n aria-label={removeAriaLabel}\n >\n <IconCross size='small' />\n </StyledChipButton>\n )}\n </>\n )\n\n if (pressable) {\n return (\n <StyledPressableChip\n type='button'\n {...(restProps as BaseButtonProps)}\n size={size}\n variant={variant}\n disabled={disabled === true || undefined}\n ref={forwardRef as React.Ref<ElementRef<typeof StyledPressableChip>>}\n aria-busy={isLoading || undefined}\n aria-disabled={isLoading || undefined}\n >\n {content}\n </StyledPressableChip>\n )\n }\n\n return (\n <StyledChip\n {...(restProps as StyledChipProps)}\n size={size}\n variant={variant}\n disabled={disabled}\n ref={forwardRef as React.Ref<ElementRef<typeof StyledChip>>}\n >\n {content}\n </StyledChip>\n )\n }\n) as ForwardRefExoticComponent<ChipProps> & Partials\n\nexport interface Partials {\n ImageSlot: typeof ImageSlot\n}\n\nChip.ImageSlot = ImageSlot\n"],"names":["styled","Primitive","BaseButton","focus","jsxs","Fragment","jsx","Spinner","IconCross"],"mappings":"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"}
package/dist/module.js CHANGED
@@ -1,61 +1,306 @@
1
- import { jsxs, jsx } from 'react/jsx-runtime';
1
+ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
  import { IconCross } from '@mirohq/design-system-icons';
4
+ import { Spinner } from '@mirohq/design-system-spinner';
4
5
  import { styled } from '@mirohq/design-system-stitches';
5
6
  import { Primitive } from '@mirohq/design-system-primitive';
6
7
  import { BaseButton } from '@mirohq/design-system-base-button';
7
8
  import { focus } from '@mirohq/design-system-styles';
8
9
 
9
- const StyledChip = styled(Primitive.div, {
10
- fontSize: "$150",
11
- lineHeight: 1.3,
12
- padding: "$50 $100",
10
+ const StyledImageSlot = styled(Primitive.span, {
11
+ display: "inline-flex",
12
+ alignItems: "center",
13
+ justifyContent: "center",
14
+ flexShrink: 0,
15
+ verticalAlign: "middle",
16
+ paddingInline: "$50",
17
+ "& img": {
18
+ display: "block",
19
+ square: 16,
20
+ borderRadius: "$round",
21
+ objectFit: "cover"
22
+ }
23
+ });
24
+
25
+ const LABEL_OFFSET = 2;
26
+ const imageSlotImg = (size) => ({
27
+ ["& ".concat(StyledImageSlot, " img")]: {
28
+ square: size
29
+ }
30
+ });
31
+ const chipLayout = {
13
32
  borderRadius: "$round",
14
33
  display: "inline-flex",
15
34
  alignItems: "center",
16
- gap: "$50",
17
- backgroundColor: "$chip-background",
18
- color: "$chip-text",
35
+ width: "fit-content",
19
36
  maxWidth: "100%",
37
+ flexShrink: 0,
38
+ boxSizing: "border-box",
39
+ border: "1px solid transparent",
40
+ lineHeight: 1.3,
41
+ // Chip labels are regular. Pressable uses BaseButton; don't keep Button's
42
+ // semibold from that shell.
43
+ fontWeight: "$regular"
44
+ };
45
+ const chipSizes = {
46
+ "x-large": {
47
+ height: "$12",
48
+ fontSize: "$200",
49
+ paddingX: "calc($200 + ".concat(LABEL_OFFSET, "px)"),
50
+ ...imageSlotImg("$8")
51
+ },
52
+ large: {
53
+ height: "$10",
54
+ fontSize: "$200",
55
+ paddingX: "calc($150 + ".concat(LABEL_OFFSET, "px)"),
56
+ ...imageSlotImg("$6")
57
+ },
58
+ medium: {
59
+ height: "$8",
60
+ fontSize: "$175",
61
+ paddingX: "calc($100 + ".concat(LABEL_OFFSET, "px)"),
62
+ ...imageSlotImg("$5")
63
+ },
64
+ small: {
65
+ height: "$6",
66
+ fontSize: "$175",
67
+ paddingX: "calc($100 + ".concat(LABEL_OFFSET, "px)"),
68
+ ...imageSlotImg("$4")
69
+ }
70
+ };
71
+ const defaultIdle = {
72
+ color: "$chip-text-on-default",
73
+ backgroundColor: "$chip-background-default",
74
+ borderColor: "$chip-border-default"
75
+ };
76
+ const outlineIdle = {
77
+ color: "$chip-text-on-outline",
78
+ backgroundColor: "$transparent",
79
+ borderColor: "$chip-border-outline"
80
+ };
81
+ const defaultInteractive = {
82
+ ...defaultIdle,
83
+ _hover: {
84
+ color: "$chip-text-on-default",
85
+ backgroundColor: "$chip-background-default-hover",
86
+ borderColor: "$chip-border-default-hover"
87
+ },
88
+ "&[data-pressed]": {
89
+ color: "$chip-text-on-default",
90
+ backgroundColor: "$chip-background-default-pressed",
91
+ borderColor: "$chip-border-default"
92
+ },
93
+ // Attribute selector so `disabled` reaches BaseButton / usePress.
94
+ "&[disabled]": {
95
+ backgroundColor: "$background-disabled",
96
+ color: "$text-on-disabled"
97
+ }
98
+ };
99
+ const outlineInteractive = {
100
+ ...outlineIdle,
101
+ _hover: {
102
+ backgroundColor: "$chip-background-outline-hover",
103
+ borderColor: "$chip-border-outline-hover",
104
+ color: "$chip-text-on-outline"
105
+ },
106
+ "&[data-pressed]": {
107
+ backgroundColor: "$chip-background-outline-pressed",
108
+ borderColor: "$chip-border-outline-pressed",
109
+ color: "$chip-text-on-outline"
110
+ },
111
+ "&[disabled]": {
112
+ backgroundColor: "$transparent",
113
+ borderColor: "$border-disabled",
114
+ color: "$text-disabled"
115
+ }
116
+ };
117
+ const StyledChip = styled(Primitive.div, {
118
+ ...chipLayout,
20
119
  variants: {
120
+ variant: {
121
+ default: defaultIdle,
122
+ outline: outlineIdle
123
+ },
21
124
  disabled: {
22
- true: {
23
- backgroundColor: "$chip-background-disabled"
125
+ true: {}
126
+ },
127
+ size: chipSizes
128
+ },
129
+ compoundVariants: [
130
+ {
131
+ variant: "default",
132
+ disabled: true,
133
+ css: {
134
+ backgroundColor: "$background-disabled",
135
+ color: "$text-on-disabled",
136
+ "& button": {
137
+ color: "$icon-on-disabled"
138
+ }
139
+ }
140
+ },
141
+ {
142
+ variant: "outline",
143
+ disabled: true,
144
+ css: {
145
+ backgroundColor: "$transparent",
146
+ borderColor: "$border-disabled",
147
+ color: "$text-disabled",
148
+ "& button": {
149
+ color: "$icon-disabled"
150
+ }
24
151
  }
25
152
  }
153
+ ],
154
+ defaultVariants: {
155
+ variant: "default",
156
+ size: "medium"
157
+ }
158
+ });
159
+ const StyledPressableChip = styled(BaseButton, {
160
+ ...chipLayout,
161
+ position: "relative",
162
+ ...focus.css({
163
+ boxShadow: "$focus"
164
+ }),
165
+ // Loading stays visually idle — only the wait cursor signals it. Don't reuse
166
+ // the disabled mute; that made loading look broken.
167
+ '&[aria-busy="true"]': {
168
+ cursor: "wait",
169
+ pointerEvents: "none"
170
+ },
171
+ variants: {
172
+ variant: {
173
+ default: defaultInteractive,
174
+ outline: outlineInteractive
175
+ },
176
+ size: chipSizes
177
+ },
178
+ defaultVariants: {
179
+ variant: "default",
180
+ size: "medium"
26
181
  }
27
182
  });
28
183
  const StyledChipContent = styled(Primitive.div, {
29
184
  overflow: "hidden",
30
185
  whiteSpace: "nowrap",
31
- textOverflow: "ellipsis"
186
+ textOverflow: "ellipsis",
187
+ // Taller than the em box so descenders (g, y) aren't clipped by overflow.
188
+ lineHeight: 1.3,
189
+ minWidth: 0,
190
+ display: "flex",
191
+ alignItems: "center",
192
+ variants: {
193
+ loading: {
194
+ true: {
195
+ opacity: 0
196
+ }
197
+ }
198
+ }
199
+ });
200
+ const StyledSpinnerBox = styled(Primitive.div, {
201
+ display: "flex",
202
+ alignItems: "center",
203
+ justifyContent: "center",
204
+ position: "absolute",
205
+ top: 0,
206
+ left: 0,
207
+ bottom: 0,
208
+ right: 0,
209
+ margin: "auto",
210
+ zIndex: 1
32
211
  });
33
212
  const StyledChipButton = styled(BaseButton, {
213
+ // Figma Chip: spacing-100 before the close glyph, not container gap.
214
+ paddingInlineStart: "$100",
215
+ flexShrink: 0,
34
216
  color: "$icon-secondary",
35
217
  ...focus.css({
36
218
  boxShadow: "$focus"
37
219
  })
38
220
  });
39
221
 
40
- const StyledImageSlot = styled(Primitive.span, {
41
- paddingInline: "$50"
42
- });
43
-
44
222
  const ImageSlot = StyledImageSlot;
45
223
 
224
+ const hasPressEvent = (props) => {
225
+ if ("onClick" in props && props.onClick != null) return true;
226
+ if ("onPress" in props && props.onPress != null) return true;
227
+ return false;
228
+ };
46
229
  const Chip = React.forwardRef(
47
- ({ children, removable = true, onRemove, removeAriaLabel, ...restProps }, forwardRef) => /* @__PURE__ */ jsxs(StyledChip, { ...restProps, ref: forwardRef, children: [
48
- /* @__PURE__ */ jsx(StyledChipContent, { children }),
49
- removable && /* @__PURE__ */ jsx(
50
- StyledChipButton,
230
+ (props, forwardRef) => {
231
+ const {
232
+ children,
233
+ removable = true,
234
+ onRemove,
235
+ removeAriaLabel,
236
+ loading = false,
237
+ size = "medium",
238
+ variant = "default",
239
+ disabled,
240
+ ...restProps
241
+ } = props;
242
+ const pressable = hasPressEvent(restProps);
243
+ const isLoading = pressable && loading;
244
+ let spinnerSize = "medium";
245
+ if (typeof size === "string" && ["small", "medium"].includes(size)) {
246
+ spinnerSize = "small";
247
+ }
248
+ const content = /* @__PURE__ */ jsxs(Fragment, { children: [
249
+ isLoading && /* @__PURE__ */ jsx(
250
+ StyledSpinnerBox,
251
+ {
252
+ "aria-hidden": true,
253
+ "data-testid": process.env.NODE_ENV === "test" ? "chip-spinner" : void 0,
254
+ children: /* @__PURE__ */ jsx(Spinner, { size: spinnerSize })
255
+ }
256
+ ),
257
+ /* @__PURE__ */ jsx(
258
+ StyledChipContent,
259
+ {
260
+ "data-chip-content": "",
261
+ loading: isLoading || void 0,
262
+ children
263
+ }
264
+ ),
265
+ !pressable && removable && /* @__PURE__ */ jsx(
266
+ StyledChipButton,
267
+ {
268
+ type: "button",
269
+ disabled: disabled === true || void 0,
270
+ onClick: onRemove,
271
+ "aria-label": removeAriaLabel,
272
+ children: /* @__PURE__ */ jsx(IconCross, { size: "small" })
273
+ }
274
+ )
275
+ ] });
276
+ if (pressable) {
277
+ return /* @__PURE__ */ jsx(
278
+ StyledPressableChip,
279
+ {
280
+ type: "button",
281
+ ...restProps,
282
+ size,
283
+ variant,
284
+ disabled: disabled === true || void 0,
285
+ ref: forwardRef,
286
+ "aria-busy": isLoading || void 0,
287
+ "aria-disabled": isLoading || void 0,
288
+ children: content
289
+ }
290
+ );
291
+ }
292
+ return /* @__PURE__ */ jsx(
293
+ StyledChip,
51
294
  {
52
- type: "button",
53
- onClick: onRemove,
54
- "aria-label": removeAriaLabel,
55
- children: /* @__PURE__ */ jsx(IconCross, { size: "small" })
295
+ ...restProps,
296
+ size,
297
+ variant,
298
+ disabled,
299
+ ref: forwardRef,
300
+ children: content
56
301
  }
57
- )
58
- ] })
302
+ );
303
+ }
59
304
  );
60
305
  Chip.ImageSlot = ImageSlot;
61
306
 
@@ -1 +1 @@
1
- {"version":3,"file":"module.js","sources":["../src/chip.styled.tsx","../src/partials/image-icon.styled.tsx","../src/partials/image-slot.tsx","../src/chip.tsx"],"sourcesContent":["import { styled } from '@mirohq/design-system-stitches'\nimport type { StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\nimport { BaseButton } from '@mirohq/design-system-base-button'\nimport { focus } from '@mirohq/design-system-styles'\n\nexport const StyledChip = styled(Primitive.div, {\n fontSize: '$150',\n lineHeight: 1.3,\n padding: '$50 $100',\n borderRadius: '$round',\n display: 'inline-flex',\n alignItems: 'center',\n gap: '$50',\n backgroundColor: '$chip-background',\n color: '$chip-text',\n maxWidth: '100%',\n variants: {\n disabled: {\n true: {\n backgroundColor: '$chip-background-disabled',\n },\n },\n },\n})\n\nexport const StyledChipContent = styled(Primitive.div, {\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n})\n\nexport const StyledChipButton = styled(BaseButton, {\n color: '$icon-secondary',\n ...focus.css({\n boxShadow: '$focus',\n }),\n})\n\nexport type StyledChipProps = StrictComponentProps<typeof StyledChip>\n","import type { StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { styled } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\n\nexport const StyledImageSlot = styled(Primitive.span, {\n paddingInline: '$50',\n})\n\nexport type StyledImageSlotProps = StrictComponentProps<typeof StyledImageSlot>\n","import type { StyledImageSlotProps } from './image-icon.styled'\nimport { StyledImageSlot } from './image-icon.styled'\n\nexport interface ImageSlotProps extends StyledImageSlotProps {}\n\nexport const ImageSlot = StyledImageSlot\n","import React from 'react'\nimport type { ElementRef, ForwardRefExoticComponent } from 'react'\nimport { IconCross } from '@mirohq/design-system-icons'\n\nimport { StyledChip, StyledChipButton, StyledChipContent } from './chip.styled'\nimport type { StyledChipProps } from './chip.styled'\nimport { ImageSlot } from './partials/image-slot'\n\ninterface RemovableProps {\n /**\n * Event handler called when the chip's remove button is clicked.\n */\n onRemove: (event: React.MouseEvent<HTMLButtonElement, MouseEvent>) => void\n\n /**\n * Remove button label to make the button recognizable by the screen readers.\n */\n removeAriaLabel: string\n}\n\nexport type ChipProps = (StyledChipProps & {\n /**\n * Show a button to remove the Chip\n * @default true\n */\n removable?: boolean\n}) &\n (\n | RemovableProps\n | { removable: false; removeAriaLabel?: never; onRemove?: never }\n )\n\nexport const Chip = React.forwardRef<ElementRef<typeof StyledChip>, ChipProps>(\n (\n { children, removable = true, onRemove, removeAriaLabel, ...restProps },\n forwardRef\n ) => (\n <StyledChip {...restProps} ref={forwardRef}>\n <StyledChipContent>{children}</StyledChipContent>\n {removable && (\n <StyledChipButton\n type='button'\n onClick={onRemove}\n aria-label={removeAriaLabel}\n >\n <IconCross size='small' />\n </StyledChipButton>\n )}\n </StyledChip>\n )\n) as ForwardRefExoticComponent<ChipProps> & Partials\n\nexport interface Partials {\n ImageSlot: typeof ImageSlot\n}\n\nChip.ImageSlot = ImageSlot\n"],"names":[],"mappings":";;;;;;;;AAMO,MAAM,UAAA,GAAa,MAAA,CAAO,SAAA,CAAU,GAAA,EAAK;AAAA,EAC9C,QAAA,EAAU,MAAA;AAAA,EACV,UAAA,EAAY,GAAA;AAAA,EACZ,OAAA,EAAS,UAAA;AAAA,EACT,YAAA,EAAc,QAAA;AAAA,EACd,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,GAAA,EAAK,KAAA;AAAA,EACL,eAAA,EAAiB,kBAAA;AAAA,EACjB,KAAA,EAAO,YAAA;AAAA,EACP,QAAA,EAAU,MAAA;AAAA,EACV,QAAA,EAAU;AAAA,IACR,QAAA,EAAU;AAAA,MACR,IAAA,EAAM;AAAA,QACJ,eAAA,EAAiB;AAAA;AACnB;AACF;AAEJ,CAAC,CAAA;AAEM,MAAM,iBAAA,GAAoB,MAAA,CAAO,SAAA,CAAU,GAAA,EAAK;AAAA,EACrD,QAAA,EAAU,QAAA;AAAA,EACV,UAAA,EAAY,QAAA;AAAA,EACZ,YAAA,EAAc;AAChB,CAAC,CAAA;AAEM,MAAM,gBAAA,GAAmB,OAAO,UAAA,EAAY;AAAA,EACjD,KAAA,EAAO,iBAAA;AAAA,EACP,GAAG,MAAM,GAAA,CAAI;AAAA,IACX,SAAA,EAAW;AAAA,GACZ;AACH,CAAC,CAAA;;ACjCM,MAAM,eAAA,GAAkB,MAAA,CAAO,SAAA,CAAU,IAAA,EAAM;AAAA,EACpD,aAAA,EAAe;AACjB,CAAC,CAAA;;ACDM,MAAM,SAAA,GAAY,eAAA;;AC2BlB,MAAM,OAAO,KAAA,CAAM,UAAA;AAAA,EACxB,CACE,EAAE,QAAA,EAAU,SAAA,GAAY,IAAA,EAAM,UAAU,eAAA,EAAiB,GAAG,SAAA,EAAU,EACtE,+BAEA,IAAA,CAAC,UAAA,EAAA,EAAY,GAAG,SAAA,EAAW,KAAK,UAAA,EAC9B,QAAA,EAAA;AAAA,oBAAA,GAAA,CAAC,qBAAmB,QAAA,EAAS,CAAA;AAAA,IAC5B,SAAA,oBACC,GAAA;AAAA,MAAC,gBAAA;AAAA,MAAA;AAAA,QACC,IAAA,EAAK,QAAA;AAAA,QACL,OAAA,EAAS,QAAA;AAAA,QACT,YAAA,EAAY,eAAA;AAAA,QAEZ,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,IAAA,EAAK,OAAA,EAAQ;AAAA;AAAA;AAC1B,GAAA,EAEJ;AAEJ;AAMA,IAAA,CAAK,SAAA,GAAY,SAAA;;;;"}
1
+ {"version":3,"file":"module.js","sources":["../src/partials/image-icon.styled.tsx","../src/chip.styled.tsx","../src/partials/image-slot.tsx","../src/chip.tsx"],"sourcesContent":["import type { StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { styled } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\n\nexport const StyledImageSlot = styled(Primitive.span, {\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n flexShrink: 0,\n verticalAlign: 'middle',\n paddingInline: '$50',\n '& img': {\n display: 'block',\n square: 16,\n borderRadius: '$round',\n objectFit: 'cover',\n },\n})\n\nexport type StyledImageSlotProps = StrictComponentProps<typeof StyledImageSlot>\n","import { styled } from '@mirohq/design-system-stitches'\nimport type { CSS, StrictComponentProps } from '@mirohq/design-system-stitches'\nimport { Primitive } from '@mirohq/design-system-primitive'\nimport { BaseButton } from '@mirohq/design-system-base-button'\nimport { focus } from '@mirohq/design-system-styles'\n\nimport { StyledImageSlot } from './partials/image-icon.styled'\n\n// Same offset Button uses so paddingX matches that scale without importing it.\nconst LABEL_OFFSET = 2\n\nconst imageSlotImg = (size: string): CSS => ({\n [`& ${StyledImageSlot} img`]: {\n square: size,\n },\n})\n\nconst chipLayout = {\n borderRadius: '$round',\n display: 'inline-flex',\n alignItems: 'center',\n width: 'fit-content',\n maxWidth: '100%',\n flexShrink: 0,\n boxSizing: 'border-box',\n border: '1px solid transparent',\n lineHeight: 1.3,\n // Chip labels are regular. Pressable uses BaseButton; don't keep Button's\n // semibold from that shell.\n fontWeight: '$regular',\n}\n\n// Copied from Button's size variant (same tokens and padding formula), not\n// imported — Chip owns this scale so Button can change independently.\nconst chipSizes = {\n 'x-large': {\n height: '$12',\n fontSize: '$200',\n paddingX: `calc($200 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$8'),\n },\n large: {\n height: '$10',\n fontSize: '$200',\n paddingX: `calc($150 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$6'),\n },\n medium: {\n height: '$8',\n fontSize: '$175',\n paddingX: `calc($100 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$5'),\n },\n small: {\n height: '$6',\n fontSize: '$175',\n paddingX: `calc($100 + ${LABEL_OFFSET}px)`,\n ...imageSlotImg('$4'),\n },\n}\n\n// Hover and pressed only belong on the pressable shell.\nconst defaultIdle = {\n color: '$chip-text-on-default',\n backgroundColor: '$chip-background-default',\n borderColor: '$chip-border-default',\n}\n\nconst outlineIdle = {\n color: '$chip-text-on-outline',\n backgroundColor: '$transparent',\n borderColor: '$chip-border-outline',\n}\n\nconst defaultInteractive = {\n ...defaultIdle,\n _hover: {\n color: '$chip-text-on-default',\n backgroundColor: '$chip-background-default-hover',\n borderColor: '$chip-border-default-hover',\n },\n '&[data-pressed]': {\n color: '$chip-text-on-default',\n backgroundColor: '$chip-background-default-pressed',\n borderColor: '$chip-border-default',\n },\n // Attribute selector so `disabled` reaches BaseButton / usePress.\n '&[disabled]': {\n backgroundColor: '$background-disabled',\n color: '$text-on-disabled',\n },\n}\n\nconst outlineInteractive = {\n ...outlineIdle,\n _hover: {\n backgroundColor: '$chip-background-outline-hover',\n borderColor: '$chip-border-outline-hover',\n color: '$chip-text-on-outline',\n },\n '&[data-pressed]': {\n backgroundColor: '$chip-background-outline-pressed',\n borderColor: '$chip-border-outline-pressed',\n color: '$chip-text-on-outline',\n },\n '&[disabled]': {\n backgroundColor: '$transparent',\n borderColor: '$border-disabled',\n color: '$text-disabled',\n },\n}\n\nexport const StyledChip = styled(Primitive.div, {\n ...chipLayout,\n variants: {\n variant: {\n default: defaultIdle,\n outline: outlineIdle,\n },\n disabled: {\n true: {},\n },\n size: chipSizes,\n },\n compoundVariants: [\n {\n variant: 'default',\n disabled: true,\n css: {\n backgroundColor: '$background-disabled',\n color: '$text-on-disabled',\n '& button': {\n color: '$icon-on-disabled',\n },\n },\n },\n {\n variant: 'outline',\n disabled: true,\n css: {\n backgroundColor: '$transparent',\n borderColor: '$border-disabled',\n color: '$text-disabled',\n '& button': {\n color: '$icon-disabled',\n },\n },\n },\n ],\n defaultVariants: {\n variant: 'default',\n size: 'medium',\n },\n})\n\nexport const StyledPressableChip = styled(BaseButton, {\n ...chipLayout,\n position: 'relative',\n ...focus.css({\n boxShadow: '$focus',\n }),\n // Loading stays visually idle — only the wait cursor signals it. Don't reuse\n // the disabled mute; that made loading look broken.\n '&[aria-busy=\"true\"]': {\n cursor: 'wait',\n pointerEvents: 'none',\n },\n variants: {\n variant: {\n default: defaultInteractive,\n outline: outlineInteractive,\n },\n size: chipSizes,\n },\n defaultVariants: {\n variant: 'default',\n size: 'medium',\n },\n})\n\nexport const StyledChipContent = styled(Primitive.div, {\n overflow: 'hidden',\n whiteSpace: 'nowrap',\n textOverflow: 'ellipsis',\n // Taller than the em box so descenders (g, y) aren't clipped by overflow.\n lineHeight: 1.3,\n minWidth: 0,\n display: 'flex',\n alignItems: 'center',\n variants: {\n loading: {\n true: {\n opacity: 0,\n },\n },\n },\n})\n\nexport const StyledSpinnerBox = styled(Primitive.div, {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n position: 'absolute',\n top: 0,\n left: 0,\n bottom: 0,\n right: 0,\n margin: 'auto',\n zIndex: 1,\n})\n\nexport const StyledChipButton = styled(BaseButton, {\n // Figma Chip: spacing-100 before the close glyph, not container gap.\n paddingInlineStart: '$100',\n flexShrink: 0,\n color: '$icon-secondary',\n ...focus.css({\n boxShadow: '$focus',\n }),\n})\n\nexport type StyledChipProps = StrictComponentProps<typeof StyledChip>\n","import type { StyledImageSlotProps } from './image-icon.styled'\nimport { StyledImageSlot } from './image-icon.styled'\n\nexport interface ImageSlotProps extends StyledImageSlotProps {}\n\nexport const ImageSlot = StyledImageSlot\n","import React from 'react'\nimport type {\n ElementRef,\n ForwardRefExoticComponent,\n RefAttributes,\n} from 'react'\nimport type { BaseButtonProps } from '@mirohq/design-system-base-button'\nimport { IconCross } from '@mirohq/design-system-icons'\nimport { Spinner } from '@mirohq/design-system-spinner'\nimport type { SpinnerProps } from '@mirohq/design-system-spinner'\n\nimport {\n StyledChip,\n StyledChipButton,\n StyledChipContent,\n StyledPressableChip,\n StyledSpinnerBox,\n} from './chip.styled'\nimport type { StyledChipProps } from './chip.styled'\nimport { ImageSlot } from './partials/image-slot'\n\nexport type ChipProps = Omit<\n StyledChipProps,\n 'ref' | 'size' | 'variant' | 'disabled'\n> &\n Pick<BaseButtonProps, 'onPress'> &\n RefAttributes<HTMLDivElement | HTMLButtonElement> & {\n /**\n * Change the chip size. Same scale as Button (`small`, `medium`, `large`,\n * `x-large`).\n * @default 'medium'\n */\n size?: StyledChipProps['size']\n /**\n * Change the chip style. `default` is filled; `outline` is bordered.\n * @default 'default'\n */\n variant?: StyledChipProps['variant']\n /**\n * Disable the chip. When removable, the close control is disabled too.\n */\n disabled?: boolean\n /**\n * Show a button to remove the Chip\n * @default true\n */\n removable?: boolean\n /**\n * Show a spinner overlay and keep the chip non-interactive without the\n * disabled look. Pressable only.\n * @default false\n */\n loading?: boolean\n } & (\n | {\n /**\n * Event handler called when the chip's remove button is clicked.\n */\n onRemove: (\n event: React.MouseEvent<HTMLButtonElement, MouseEvent>\n ) => void\n /**\n * Remove button label to make the button recognizable by the screen readers.\n */\n removeAriaLabel: string\n }\n | { removable: false; removeAriaLabel?: never; onRemove?: never }\n )\n\nconst hasPressEvent = (props: object): boolean => {\n if ('onClick' in props && props.onClick != null) return true\n if ('onPress' in props && props.onPress != null) return true\n\n return false\n}\n\nexport const Chip = React.forwardRef<ElementRef<'div' | 'button'>, ChipProps>(\n (props, forwardRef) => {\n const {\n children,\n removable = true,\n onRemove,\n removeAriaLabel,\n loading = false,\n size = 'medium',\n variant = 'default',\n disabled,\n ...restProps\n } = props\n\n const pressable = hasPressEvent(restProps)\n const isLoading = pressable && loading\n\n let spinnerSize: SpinnerProps['size'] = 'medium'\n\n if (typeof size === 'string' && ['small', 'medium'].includes(size)) {\n spinnerSize = 'small'\n }\n\n const content = (\n <>\n {isLoading && (\n <StyledSpinnerBox\n aria-hidden\n data-testid={\n process.env.NODE_ENV === 'test' ? 'chip-spinner' : undefined\n }\n >\n <Spinner size={spinnerSize} />\n </StyledSpinnerBox>\n )}\n <StyledChipContent\n data-chip-content=''\n loading={isLoading || undefined}\n >\n {children}\n </StyledChipContent>\n {!pressable && removable && (\n <StyledChipButton\n type='button'\n disabled={disabled === true || undefined}\n onClick={onRemove}\n aria-label={removeAriaLabel}\n >\n <IconCross size='small' />\n </StyledChipButton>\n )}\n </>\n )\n\n if (pressable) {\n return (\n <StyledPressableChip\n type='button'\n {...(restProps as BaseButtonProps)}\n size={size}\n variant={variant}\n disabled={disabled === true || undefined}\n ref={forwardRef as React.Ref<ElementRef<typeof StyledPressableChip>>}\n aria-busy={isLoading || undefined}\n aria-disabled={isLoading || undefined}\n >\n {content}\n </StyledPressableChip>\n )\n }\n\n return (\n <StyledChip\n {...(restProps as StyledChipProps)}\n size={size}\n variant={variant}\n disabled={disabled}\n ref={forwardRef as React.Ref<ElementRef<typeof StyledChip>>}\n >\n {content}\n </StyledChip>\n )\n }\n) as ForwardRefExoticComponent<ChipProps> & Partials\n\nexport interface Partials {\n ImageSlot: typeof ImageSlot\n}\n\nChip.ImageSlot = ImageSlot\n"],"names":[],"mappings":";;;;;;;;;AAIO,MAAM,eAAA,GAAkB,MAAA,CAAO,SAAA,CAAU,IAAA,EAAM;AAAA,EACpD,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,cAAA,EAAgB,QAAA;AAAA,EAChB,UAAA,EAAY,CAAA;AAAA,EACZ,aAAA,EAAe,QAAA;AAAA,EACf,aAAA,EAAe,KAAA;AAAA,EACf,OAAA,EAAS;AAAA,IACP,OAAA,EAAS,OAAA;AAAA,IACT,MAAA,EAAQ,EAAA;AAAA,IACR,YAAA,EAAc,QAAA;AAAA,IACd,SAAA,EAAW;AAAA;AAEf,CAAC,CAAA;;ACRD,MAAM,YAAA,GAAe,CAAA;AAErB,MAAM,YAAA,GAAe,CAAC,IAAA,MAAuB;AAAA,EAC3C,CAAC,IAAA,CAAK,MAAA,CAAA,eAAA,EAAe,MAAA,CAAM,GAAG;AAAA,IAC5B,MAAA,EAAQ;AAAA;AAEZ,CAAA,CAAA;AAEA,MAAM,UAAA,GAAa;AAAA,EACjB,YAAA,EAAc,QAAA;AAAA,EACd,OAAA,EAAS,aAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,KAAA,EAAO,aAAA;AAAA,EACP,QAAA,EAAU,MAAA;AAAA,EACV,UAAA,EAAY,CAAA;AAAA,EACZ,SAAA,EAAW,YAAA;AAAA,EACX,MAAA,EAAQ,uBAAA;AAAA,EACR,UAAA,EAAY,GAAA;AAAA;AAAA;AAAA,EAGZ,UAAA,EAAY;AACd,CAAA;AAIA,MAAM,SAAA,GAAY;AAAA,EAChB,SAAA,EAAW;AAAA,IACT,MAAA,EAAQ,KAAA;AAAA,IACR,QAAA,EAAU,MAAA;AAAA,IACV,QAAA,EAAU,eAAe,MAAA,CAAA,YAAA,EAAY,KAAA,CAAA;AAAA,IACrC,GAAG,aAAa,IAAI;AAAA,GACtB;AAAA,EACA,KAAA,EAAO;AAAA,IACL,MAAA,EAAQ,KAAA;AAAA,IACR,QAAA,EAAU,MAAA;AAAA,IACV,QAAA,EAAU,eAAe,MAAA,CAAA,YAAA,EAAY,KAAA,CAAA;AAAA,IACrC,GAAG,aAAa,IAAI;AAAA,GACtB;AAAA,EACA,MAAA,EAAQ;AAAA,IACN,MAAA,EAAQ,IAAA;AAAA,IACR,QAAA,EAAU,MAAA;AAAA,IACV,QAAA,EAAU,eAAe,MAAA,CAAA,YAAA,EAAY,KAAA,CAAA;AAAA,IACrC,GAAG,aAAa,IAAI;AAAA,GACtB;AAAA,EACA,KAAA,EAAO;AAAA,IACL,MAAA,EAAQ,IAAA;AAAA,IACR,QAAA,EAAU,MAAA;AAAA,IACV,QAAA,EAAU,eAAe,MAAA,CAAA,YAAA,EAAY,KAAA,CAAA;AAAA,IACrC,GAAG,aAAa,IAAI;AAAA;AAExB,CAAA;AAGA,MAAM,WAAA,GAAc;AAAA,EAClB,KAAA,EAAO,uBAAA;AAAA,EACP,eAAA,EAAiB,0BAAA;AAAA,EACjB,WAAA,EAAa;AACf,CAAA;AAEA,MAAM,WAAA,GAAc;AAAA,EAClB,KAAA,EAAO,uBAAA;AAAA,EACP,eAAA,EAAiB,cAAA;AAAA,EACjB,WAAA,EAAa;AACf,CAAA;AAEA,MAAM,kBAAA,GAAqB;AAAA,EACzB,GAAG,WAAA;AAAA,EACH,MAAA,EAAQ;AAAA,IACN,KAAA,EAAO,uBAAA;AAAA,IACP,eAAA,EAAiB,gCAAA;AAAA,IACjB,WAAA,EAAa;AAAA,GACf;AAAA,EACA,iBAAA,EAAmB;AAAA,IACjB,KAAA,EAAO,uBAAA;AAAA,IACP,eAAA,EAAiB,kCAAA;AAAA,IACjB,WAAA,EAAa;AAAA,GACf;AAAA;AAAA,EAEA,aAAA,EAAe;AAAA,IACb,eAAA,EAAiB,sBAAA;AAAA,IACjB,KAAA,EAAO;AAAA;AAEX,CAAA;AAEA,MAAM,kBAAA,GAAqB;AAAA,EACzB,GAAG,WAAA;AAAA,EACH,MAAA,EAAQ;AAAA,IACN,eAAA,EAAiB,gCAAA;AAAA,IACjB,WAAA,EAAa,4BAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA,iBAAA,EAAmB;AAAA,IACjB,eAAA,EAAiB,kCAAA;AAAA,IACjB,WAAA,EAAa,8BAAA;AAAA,IACb,KAAA,EAAO;AAAA,GACT;AAAA,EACA,aAAA,EAAe;AAAA,IACb,eAAA,EAAiB,cAAA;AAAA,IACjB,WAAA,EAAa,kBAAA;AAAA,IACb,KAAA,EAAO;AAAA;AAEX,CAAA;AAEO,MAAM,UAAA,GAAa,MAAA,CAAO,SAAA,CAAU,GAAA,EAAK;AAAA,EAC9C,GAAG,UAAA;AAAA,EACH,QAAA,EAAU;AAAA,IACR,OAAA,EAAS;AAAA,MACP,OAAA,EAAS,WAAA;AAAA,MACT,OAAA,EAAS;AAAA,KACX;AAAA,IACA,QAAA,EAAU;AAAA,MACR,MAAM;AAAC,KACT;AAAA,IACA,IAAA,EAAM;AAAA,GACR;AAAA,EACA,gBAAA,EAAkB;AAAA,IAChB;AAAA,MACE,OAAA,EAAS,SAAA;AAAA,MACT,QAAA,EAAU,IAAA;AAAA,MACV,GAAA,EAAK;AAAA,QACH,eAAA,EAAiB,sBAAA;AAAA,QACjB,KAAA,EAAO,mBAAA;AAAA,QACP,UAAA,EAAY;AAAA,UACV,KAAA,EAAO;AAAA;AACT;AACF,KACF;AAAA,IACA;AAAA,MACE,OAAA,EAAS,SAAA;AAAA,MACT,QAAA,EAAU,IAAA;AAAA,MACV,GAAA,EAAK;AAAA,QACH,eAAA,EAAiB,cAAA;AAAA,QACjB,WAAA,EAAa,kBAAA;AAAA,QACb,KAAA,EAAO,gBAAA;AAAA,QACP,UAAA,EAAY;AAAA,UACV,KAAA,EAAO;AAAA;AACT;AACF;AACF,GACF;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,OAAA,EAAS,SAAA;AAAA,IACT,IAAA,EAAM;AAAA;AAEV,CAAC,CAAA;AAEM,MAAM,mBAAA,GAAsB,OAAO,UAAA,EAAY;AAAA,EACpD,GAAG,UAAA;AAAA,EACH,QAAA,EAAU,UAAA;AAAA,EACV,GAAG,MAAM,GAAA,CAAI;AAAA,IACX,SAAA,EAAW;AAAA,GACZ,CAAA;AAAA;AAAA;AAAA,EAGD,qBAAA,EAAuB;AAAA,IACrB,MAAA,EAAQ,MAAA;AAAA,IACR,aAAA,EAAe;AAAA,GACjB;AAAA,EACA,QAAA,EAAU;AAAA,IACR,OAAA,EAAS;AAAA,MACP,OAAA,EAAS,kBAAA;AAAA,MACT,OAAA,EAAS;AAAA,KACX;AAAA,IACA,IAAA,EAAM;AAAA,GACR;AAAA,EACA,eAAA,EAAiB;AAAA,IACf,OAAA,EAAS,SAAA;AAAA,IACT,IAAA,EAAM;AAAA;AAEV,CAAC,CAAA;AAEM,MAAM,iBAAA,GAAoB,MAAA,CAAO,SAAA,CAAU,GAAA,EAAK;AAAA,EACrD,QAAA,EAAU,QAAA;AAAA,EACV,UAAA,EAAY,QAAA;AAAA,EACZ,YAAA,EAAc,UAAA;AAAA;AAAA,EAEd,UAAA,EAAY,GAAA;AAAA,EACZ,QAAA,EAAU,CAAA;AAAA,EACV,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,QAAA,EAAU;AAAA,IACR,OAAA,EAAS;AAAA,MACP,IAAA,EAAM;AAAA,QACJ,OAAA,EAAS;AAAA;AACX;AACF;AAEJ,CAAC,CAAA;AAEM,MAAM,gBAAA,GAAmB,MAAA,CAAO,SAAA,CAAU,GAAA,EAAK;AAAA,EACpD,OAAA,EAAS,MAAA;AAAA,EACT,UAAA,EAAY,QAAA;AAAA,EACZ,cAAA,EAAgB,QAAA;AAAA,EAChB,QAAA,EAAU,UAAA;AAAA,EACV,GAAA,EAAK,CAAA;AAAA,EACL,IAAA,EAAM,CAAA;AAAA,EACN,MAAA,EAAQ,CAAA;AAAA,EACR,KAAA,EAAO,CAAA;AAAA,EACP,MAAA,EAAQ,MAAA;AAAA,EACR,MAAA,EAAQ;AACV,CAAC,CAAA;AAEM,MAAM,gBAAA,GAAmB,OAAO,UAAA,EAAY;AAAA;AAAA,EAEjD,kBAAA,EAAoB,MAAA;AAAA,EACpB,UAAA,EAAY,CAAA;AAAA,EACZ,KAAA,EAAO,iBAAA;AAAA,EACP,GAAG,MAAM,GAAA,CAAI;AAAA,IACX,SAAA,EAAW;AAAA,GACZ;AACH,CAAC,CAAA;;ACtNM,MAAM,SAAA,GAAY,eAAA;;ACgEzB,MAAM,aAAA,GAAgB,CAAC,KAAA,KAA2B;AAChD,EAAA,IAAI,SAAA,IAAa,KAAA,IAAS,KAAA,CAAM,OAAA,IAAW,MAAM,OAAO,IAAA;AACxD,EAAA,IAAI,SAAA,IAAa,KAAA,IAAS,KAAA,CAAM,OAAA,IAAW,MAAM,OAAO,IAAA;AAExD,EAAA,OAAO,KAAA;AACT,CAAA;AAEO,MAAM,OAAO,KAAA,CAAM,UAAA;AAAA,EACxB,CAAC,OAAO,UAAA,KAAe;AACrB,IAAA,MAAM;AAAA,MACJ,QAAA;AAAA,MACA,SAAA,GAAY,IAAA;AAAA,MACZ,QAAA;AAAA,MACA,eAAA;AAAA,MACA,OAAA,GAAU,KAAA;AAAA,MACV,IAAA,GAAO,QAAA;AAAA,MACP,OAAA,GAAU,SAAA;AAAA,MACV,QAAA;AAAA,MACA,GAAG;AAAA,KACL,GAAI,KAAA;AAEJ,IAAA,MAAM,SAAA,GAAY,cAAc,SAAS,CAAA;AACzC,IAAA,MAAM,YAAY,SAAA,IAAa,OAAA;AAE/B,IAAA,IAAI,WAAA,GAAoC,QAAA;AAExC,IAAA,IAAI,OAAO,SAAS,QAAA,IAAY,CAAC,SAAS,QAAQ,CAAA,CAAE,QAAA,CAAS,IAAI,CAAA,EAAG;AAClE,MAAA,WAAA,GAAc,OAAA;AAAA,IAChB;AAEA,IAAA,MAAM,0BACJ,IAAA,CAAA,QAAA,EAAA,EACG,QAAA,EAAA;AAAA,MAAA,SAAA,oBACC,GAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UACC,aAAA,EAAW,IAAA;AAAA,UACX,aAAA,EACE,OAAA,CAAQ,GAAA,CAAI,QAAA,KAAa,SAAS,cAAA,GAAiB,MAAA;AAAA,UAGrD,QAAA,kBAAA,GAAA,CAAC,OAAA,EAAA,EAAQ,IAAA,EAAM,WAAA,EAAa;AAAA;AAAA,OAC9B;AAAA,sBAEF,GAAA;AAAA,QAAC,iBAAA;AAAA,QAAA;AAAA,UACC,mBAAA,EAAkB,EAAA;AAAA,UAClB,SAAS,SAAA,IAAa,MAAA;AAAA,UAErB;AAAA;AAAA,OACH;AAAA,MACC,CAAC,aAAa,SAAA,oBACb,GAAA;AAAA,QAAC,gBAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACL,QAAA,EAAU,aAAa,IAAA,IAAQ,MAAA;AAAA,UAC/B,OAAA,EAAS,QAAA;AAAA,UACT,YAAA,EAAY,eAAA;AAAA,UAEZ,QAAA,kBAAA,GAAA,CAAC,SAAA,EAAA,EAAU,IAAA,EAAK,OAAA,EAAQ;AAAA;AAAA;AAC1B,KAAA,EAEJ,CAAA;AAGF,IAAA,IAAI,SAAA,EAAW;AACb,MAAA,uBACE,GAAA;AAAA,QAAC,mBAAA;AAAA,QAAA;AAAA,UACC,IAAA,EAAK,QAAA;AAAA,UACJ,GAAI,SAAA;AAAA,UACL,IAAA;AAAA,UACA,OAAA;AAAA,UACA,QAAA,EAAU,aAAa,IAAA,IAAQ,MAAA;AAAA,UAC/B,GAAA,EAAK,UAAA;AAAA,UACL,aAAW,SAAA,IAAa,MAAA;AAAA,UACxB,iBAAe,SAAA,IAAa,MAAA;AAAA,UAE3B,QAAA,EAAA;AAAA;AAAA,OACH;AAAA,IAEJ;AAEA,IAAA,uBACE,GAAA;AAAA,MAAC,UAAA;AAAA,MAAA;AAAA,QACE,GAAI,SAAA;AAAA,QACL,IAAA;AAAA,QACA,OAAA;AAAA,QACA,QAAA;AAAA,QACA,GAAA,EAAK,UAAA;AAAA,QAEJ,QAAA,EAAA;AAAA;AAAA,KACH;AAAA,EAEJ;AACF;AAMA,IAAA,CAAK,SAAA,GAAY,SAAA;;;;"}
package/dist/types.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import * as react from 'react';
2
- import react__default, { ForwardRefExoticComponent } from 'react';
2
+ import react__default, { ForwardRefExoticComponent, RefAttributes } from 'react';
3
+ import { BaseButtonProps } from '@mirohq/design-system-base-button';
3
4
  import * as _mirohq_design_system_stitches from '@mirohq/design-system-stitches';
4
5
  import { StrictComponentProps } from '@mirohq/design-system-stitches';
5
6
  import * as _mirohq_design_system_primitive from '@mirohq/design-system-primitive';
@@ -25,10 +26,14 @@ type TransformProps<Props, Media> = {
25
26
  )
26
27
  }
27
28
 
28
- declare const StyledChip: react.ForwardRefExoticComponent<Omit<Omit<_mirohq_design_system_stitches.StyledComponentProps<react.ForwardRefExoticComponent<_mirohq_design_system_primitive.PrimitiveProps<"div">>>, "disabled"> & TransformProps<{
29
+ declare const StyledChip: react.ForwardRefExoticComponent<Omit<Omit<_mirohq_design_system_stitches.StyledComponentProps<react.ForwardRefExoticComponent<_mirohq_design_system_primitive.PrimitiveProps<"div">>>, "size" | "disabled" | "variant"> & TransformProps<{
30
+ variant?: "outline" | "default" | undefined;
29
31
  disabled?: boolean | "true" | undefined;
32
+ size?: "small" | "medium" | "large" | "x-large" | undefined;
30
33
  }, {}> & _mirohq_design_system_stitches.CustomStylesProps, "ref"> & react.RefAttributes<HTMLDivElement>> & _mirohq_design_system_stitches.StitchesInternals<react.ForwardRefExoticComponent<_mirohq_design_system_primitive.PrimitiveProps<"div">>, {
34
+ variant?: "outline" | "default" | undefined;
31
35
  disabled?: boolean | "true" | undefined;
36
+ size?: "small" | "medium" | "large" | "x-large" | undefined;
32
37
  }, {}>;
33
38
  type StyledChipProps = StrictComponentProps<typeof StyledChip>;
34
39
 
@@ -39,23 +44,43 @@ interface ImageSlotProps extends StyledImageSlotProps {
39
44
  }
40
45
  declare const ImageSlot: react.ForwardRefExoticComponent<Omit<Omit<_mirohq_design_system_stitches.StyledComponentProps<react.ForwardRefExoticComponent<_mirohq_design_system_components_primitive.PrimitiveProps<"span">>>, never> & TransformProps<{}, {}> & _mirohq_design_system_stitches.CustomStylesProps, "ref"> & react.RefAttributes<HTMLSpanElement>> & _mirohq_design_system_stitches.StitchesInternals<react.ForwardRefExoticComponent<_mirohq_design_system_components_primitive.PrimitiveProps<"span">>, {}, {}>;
41
46
 
42
- interface RemovableProps {
47
+ type ChipProps = Omit<StyledChipProps, 'ref' | 'size' | 'variant' | 'disabled'> & Pick<BaseButtonProps, 'onPress'> & RefAttributes<HTMLDivElement | HTMLButtonElement> & {
43
48
  /**
44
- * Event handler called when the chip's remove button is clicked.
49
+ * Change the chip size. Same scale as Button (`small`, `medium`, `large`,
50
+ * `x-large`).
51
+ * @default 'medium'
45
52
  */
46
- onRemove: (event: react__default.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
53
+ size?: StyledChipProps['size'];
47
54
  /**
48
- * Remove button label to make the button recognizable by the screen readers.
55
+ * Change the chip style. `default` is filled; `outline` is bordered.
56
+ * @default 'default'
49
57
  */
50
- removeAriaLabel: string;
51
- }
52
- type ChipProps = (StyledChipProps & {
58
+ variant?: StyledChipProps['variant'];
59
+ /**
60
+ * Disable the chip. When removable, the close control is disabled too.
61
+ */
62
+ disabled?: boolean;
53
63
  /**
54
64
  * Show a button to remove the Chip
55
65
  * @default true
56
66
  */
57
67
  removable?: boolean;
58
- }) & (RemovableProps | {
68
+ /**
69
+ * Show a spinner overlay and keep the chip non-interactive without the
70
+ * disabled look. Pressable only.
71
+ * @default false
72
+ */
73
+ loading?: boolean;
74
+ } & ({
75
+ /**
76
+ * Event handler called when the chip's remove button is clicked.
77
+ */
78
+ onRemove: (event: react__default.MouseEvent<HTMLButtonElement, MouseEvent>) => void;
79
+ /**
80
+ * Remove button label to make the button recognizable by the screen readers.
81
+ */
82
+ removeAriaLabel: string;
83
+ } | {
59
84
  removable: false;
60
85
  removeAriaLabel?: never;
61
86
  onRemove?: never;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mirohq/design-system-chip",
3
- "version": "1.2.62",
3
+ "version": "1.3.0-filter-chip.1",
4
4
  "description": "",
5
5
  "author": "Miro",
6
6
  "source": "src/index.ts",
@@ -26,11 +26,12 @@
26
26
  "react": "^16.14 || ^17 || ^18 || ^19"
27
27
  },
28
28
  "dependencies": {
29
- "@mirohq/design-system-base-button": "^1.2.38",
30
29
  "@mirohq/design-system-icons": "^1.46.2",
30
+ "@mirohq/design-system-base-button": "^1.2.38",
31
+ "@mirohq/design-system-spinner": "^2.2.35",
31
32
  "@mirohq/design-system-stitches": "^3.3.33",
32
- "@mirohq/design-system-styles": "^3.2.33",
33
- "@mirohq/design-system-primitive": "^2.2.1"
33
+ "@mirohq/design-system-primitive": "^2.2.1",
34
+ "@mirohq/design-system-styles": "^3.2.33"
34
35
  },
35
36
  "scripts": {
36
37
  "build": "rollup -c ../../../rollup.config.js",