design-zystem 1.0.250 → 1.0.252

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/index.d.mts CHANGED
@@ -742,6 +742,8 @@ interface TabItem {
742
742
  id: string | number;
743
743
  label: string;
744
744
  disabled?: boolean;
745
+ dot?: boolean;
746
+ dotColor?: string;
745
747
  }
746
748
  type TabsVariant = 'line' | 'pills';
747
749
  interface TabsProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
@@ -909,6 +911,25 @@ interface EmptyStateProps {
909
911
  }
910
912
  declare const EmptyState: ({ icon, title, description, actionLabel, onAction, }: EmptyStateProps) => react_jsx_runtime.JSX.Element;
911
913
 
914
+ interface FloatingAction {
915
+ id: string;
916
+ label: string;
917
+ icon: string;
918
+ badge?: number;
919
+ onClick: () => void;
920
+ }
921
+ interface FloatingButtonProps {
922
+ isOpen: boolean;
923
+ onToggle: () => void;
924
+ actions: FloatingAction[];
925
+ mainBadge?: number;
926
+ label?: string;
927
+ icon?: string;
928
+ openIcon?: string;
929
+ variant?: keyof typeof colors;
930
+ }
931
+ declare const FloatingButton: ({ isOpen, onToggle, actions, mainBadge, label, icon, openIcon, variant, }: FloatingButtonProps) => react_jsx_runtime.JSX.Element;
932
+
912
933
  interface ProgressBarProps {
913
934
  /** Filled portion, 0–100. Values outside the range are clamped. */
914
935
  value: number;
@@ -1028,4 +1049,4 @@ interface OptimizeImageOptions {
1028
1049
  }
1029
1050
  declare const optimizeImage: (file: File | null | undefined, desiredBaseName: string, opts?: OptimizeImageOptions) => Promise<OptimizeImageResult>;
1030
1051
 
1031
- export { Accordion, type AccordionItem, Avatar, BorderedRow, Box, Bubble, Bulk, Button, CardSkeleton, Checkbox, Col, Collapse, ColorPicker, DatePicker, Divider, Drawer, EmptyState, FileUploadZone, Grid, Icon, IconTabs, Image, Input, Link, List, ListItem, MetricCard, Modal, ModalConfirmation, MultiSelect, NewModal, Options, PageContainer, Pagination, Popover, ProgressBar, Radio, Row, Select, type SelectOption, type SelectProps, SkeletonRow, SliderInput, type SortOrder, Spinner, Stepper, Switch, Table, TableBody, TableCell, TableFooter, TableFooterCell, TableFooterRow, TableHeader, TableHeaderCell, type TableHeaderCellProps, TableHeaderRow, TableRow, Tabs, TagBubble, Text, Timeline, type TimelineItem, Tooltip, colors, formatDate, formatDistance, formatDuration, optimizeImage, truncateFileName, truncateText };
1052
+ export { Accordion, type AccordionItem, Avatar, BorderedRow, Box, Bubble, Bulk, Button, CardSkeleton, Checkbox, Col, Collapse, ColorPicker, DatePicker, Divider, Drawer, EmptyState, FileUploadZone, type FloatingAction, FloatingButton, type FloatingButtonProps, Grid, Icon, IconTabs, Image, Input, Link, List, ListItem, MetricCard, Modal, ModalConfirmation, MultiSelect, NewModal, Options, PageContainer, Pagination, Popover, ProgressBar, Radio, Row, Select, type SelectOption, type SelectProps, SkeletonRow, SliderInput, type SortOrder, Spinner, Stepper, Switch, Table, TableBody, TableCell, TableFooter, TableFooterCell, TableFooterRow, TableHeader, TableHeaderCell, type TableHeaderCellProps, TableHeaderRow, TableRow, Tabs, TagBubble, Text, Timeline, type TimelineItem, Tooltip, colors, formatDate, formatDistance, formatDuration, optimizeImage, truncateFileName, truncateText };
package/dist/index.d.ts CHANGED
@@ -742,6 +742,8 @@ interface TabItem {
742
742
  id: string | number;
743
743
  label: string;
744
744
  disabled?: boolean;
745
+ dot?: boolean;
746
+ dotColor?: string;
745
747
  }
746
748
  type TabsVariant = 'line' | 'pills';
747
749
  interface TabsProps extends Omit<HTMLAttributes<HTMLDivElement>, 'onChange'> {
@@ -909,6 +911,25 @@ interface EmptyStateProps {
909
911
  }
910
912
  declare const EmptyState: ({ icon, title, description, actionLabel, onAction, }: EmptyStateProps) => react_jsx_runtime.JSX.Element;
911
913
 
914
+ interface FloatingAction {
915
+ id: string;
916
+ label: string;
917
+ icon: string;
918
+ badge?: number;
919
+ onClick: () => void;
920
+ }
921
+ interface FloatingButtonProps {
922
+ isOpen: boolean;
923
+ onToggle: () => void;
924
+ actions: FloatingAction[];
925
+ mainBadge?: number;
926
+ label?: string;
927
+ icon?: string;
928
+ openIcon?: string;
929
+ variant?: keyof typeof colors;
930
+ }
931
+ declare const FloatingButton: ({ isOpen, onToggle, actions, mainBadge, label, icon, openIcon, variant, }: FloatingButtonProps) => react_jsx_runtime.JSX.Element;
932
+
912
933
  interface ProgressBarProps {
913
934
  /** Filled portion, 0–100. Values outside the range are clamped. */
914
935
  value: number;
@@ -1028,4 +1049,4 @@ interface OptimizeImageOptions {
1028
1049
  }
1029
1050
  declare const optimizeImage: (file: File | null | undefined, desiredBaseName: string, opts?: OptimizeImageOptions) => Promise<OptimizeImageResult>;
1030
1051
 
1031
- export { Accordion, type AccordionItem, Avatar, BorderedRow, Box, Bubble, Bulk, Button, CardSkeleton, Checkbox, Col, Collapse, ColorPicker, DatePicker, Divider, Drawer, EmptyState, FileUploadZone, Grid, Icon, IconTabs, Image, Input, Link, List, ListItem, MetricCard, Modal, ModalConfirmation, MultiSelect, NewModal, Options, PageContainer, Pagination, Popover, ProgressBar, Radio, Row, Select, type SelectOption, type SelectProps, SkeletonRow, SliderInput, type SortOrder, Spinner, Stepper, Switch, Table, TableBody, TableCell, TableFooter, TableFooterCell, TableFooterRow, TableHeader, TableHeaderCell, type TableHeaderCellProps, TableHeaderRow, TableRow, Tabs, TagBubble, Text, Timeline, type TimelineItem, Tooltip, colors, formatDate, formatDistance, formatDuration, optimizeImage, truncateFileName, truncateText };
1052
+ export { Accordion, type AccordionItem, Avatar, BorderedRow, Box, Bubble, Bulk, Button, CardSkeleton, Checkbox, Col, Collapse, ColorPicker, DatePicker, Divider, Drawer, EmptyState, FileUploadZone, type FloatingAction, FloatingButton, type FloatingButtonProps, Grid, Icon, IconTabs, Image, Input, Link, List, ListItem, MetricCard, Modal, ModalConfirmation, MultiSelect, NewModal, Options, PageContainer, Pagination, Popover, ProgressBar, Radio, Row, Select, type SelectOption, type SelectProps, SkeletonRow, SliderInput, type SortOrder, Spinner, Stepper, Switch, Table, TableBody, TableCell, TableFooter, TableFooterCell, TableFooterRow, TableHeader, TableHeaderCell, type TableHeaderCellProps, TableHeaderRow, TableRow, Tabs, TagBubble, Text, Timeline, type TimelineItem, Tooltip, colors, formatDate, formatDistance, formatDuration, optimizeImage, truncateFileName, truncateText };
package/dist/index.js CHANGED
@@ -76,6 +76,7 @@ __export(index_exports, {
76
76
  Drawer: () => Drawer,
77
77
  EmptyState: () => EmptyState,
78
78
  FileUploadZone: () => FileUploadZone,
79
+ FloatingButton: () => FloatingButton,
79
80
  Grid: () => Grid,
80
81
  Icon: () => Icon,
81
82
  IconTabs: () => IconTabs,
@@ -3890,6 +3891,10 @@ var TabButton = import_styled_components38.default.button.withConfig({
3890
3891
  shouldForwardProp: shouldForwardTab
3891
3892
  })`
3892
3893
  appearance: none;
3894
+ display: inline-flex;
3895
+ align-items: center;
3896
+ justify-content: center;
3897
+ gap: 6px;
3893
3898
  border: 0;
3894
3899
  background: ${(p) => {
3895
3900
  if (p.$variant !== "pills") return "transparent";
@@ -3931,6 +3936,14 @@ var TabButton = import_styled_components38.default.button.withConfig({
3931
3936
  opacity: 0.6;
3932
3937
  }
3933
3938
  `;
3939
+ var TabDot = import_styled_components38.default.span`
3940
+ display: inline-block;
3941
+ width: 8px;
3942
+ height: 8px;
3943
+ border-radius: 50%;
3944
+ flex: none;
3945
+ background: ${(p) => p.$color || colors.red_950};
3946
+ `;
3934
3947
  var Tab = (_a) => {
3935
3948
  var _b = _a, {
3936
3949
  id,
@@ -4021,7 +4034,7 @@ var Tabs = (_a) => {
4021
4034
  const isPillsFullWidth = variant === "pills" && align === "start";
4022
4035
  const rendered = (0, import_react20.useMemo)(() => {
4023
4036
  if (items && items.length) {
4024
- return items.map((it) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
4037
+ return items.map((it) => /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
4025
4038
  Tab,
4026
4039
  {
4027
4040
  id: it.id,
@@ -4031,7 +4044,10 @@ var Tabs = (_a) => {
4031
4044
  fullWidth: isPillsFullWidth,
4032
4045
  onClick: () => handleSelect(it.id),
4033
4046
  innerRef: setTabRef(it.id),
4034
- children: it.label
4047
+ children: [
4048
+ it.label,
4049
+ it.dot && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(TabDot, { $color: it.dotColor })
4050
+ ]
4035
4051
  },
4036
4052
  it.id
4037
4053
  ));
@@ -5235,17 +5251,149 @@ var EmptyState = ({
5235
5251
  );
5236
5252
  };
5237
5253
 
5238
- // src/Components/ProgressBar/ProgressBar.tsx
5254
+ // src/Components/FloatingButton/FloatingButton.tsx
5239
5255
  var import_styled_components45 = __toESM(require("styled-components"));
5240
5256
  var import_jsx_runtime56 = require("react/jsx-runtime");
5257
+ var FloatingButton = ({
5258
+ isOpen,
5259
+ onToggle,
5260
+ actions,
5261
+ mainBadge = 0,
5262
+ label = "Menu",
5263
+ icon = "comment",
5264
+ openIcon = "xmark",
5265
+ variant = "blue_700"
5266
+ }) => {
5267
+ const accent = colors[variant];
5268
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Container6, { children: [
5269
+ actions.map((action, index) => {
5270
+ var _a;
5271
+ return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
5272
+ SubButton,
5273
+ {
5274
+ type: "button",
5275
+ "aria-label": action.label,
5276
+ $isOpen: isOpen,
5277
+ $transform: arcTransform(index, actions.length),
5278
+ onClick: action.onClick,
5279
+ children: [
5280
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Icon, { name: action.icon, family: "regular", size: "s", color: accent }),
5281
+ ((_a = action.badge) != null ? _a : 0) > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(CountBadge, { children: action.badge })
5282
+ ]
5283
+ },
5284
+ action.id
5285
+ );
5286
+ }),
5287
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(
5288
+ MainButton,
5289
+ {
5290
+ type: "button",
5291
+ "aria-label": label,
5292
+ "aria-expanded": isOpen,
5293
+ $accent: accent,
5294
+ onClick: onToggle,
5295
+ children: [
5296
+ /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
5297
+ Icon,
5298
+ {
5299
+ name: isOpen ? openIcon : icon,
5300
+ family: "regular",
5301
+ size: "m",
5302
+ color: colors.white
5303
+ }
5304
+ ),
5305
+ !isOpen && mainBadge > 0 && /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(CountBadge, { children: mainBadge })
5306
+ ]
5307
+ }
5308
+ )
5309
+ ] });
5310
+ };
5311
+ var FAB_SIZE = 56;
5312
+ var SUB_SIZE = 48;
5313
+ var ARC_RADIUS = 64;
5314
+ var ARC_START_ANGLE = 90;
5315
+ var ARC_MAX_STEP = 65;
5316
+ var ARC_MAX_SPAN = 90;
5317
+ var arcTransform = (index, total) => {
5318
+ const step = total > 1 ? Math.min(ARC_MAX_STEP, ARC_MAX_SPAN / (total - 1)) : 0;
5319
+ const angle = (ARC_START_ANGLE + index * step) * Math.PI / 180;
5320
+ const x = Math.round(Math.cos(angle) * ARC_RADIUS);
5321
+ const y = Math.round(-Math.sin(angle) * ARC_RADIUS);
5322
+ return `translate(${x}px, ${y}px)`;
5323
+ };
5324
+ var Container6 = import_styled_components45.default.div`
5325
+ position: fixed;
5326
+ right: 32px;
5327
+ bottom: 32px;
5328
+ width: ${FAB_SIZE}px;
5329
+ height: ${FAB_SIZE}px;
5330
+ z-index: 1000;
5331
+ `;
5332
+ var MainButton = import_styled_components45.default.button`
5333
+ position: absolute;
5334
+ inset: 0;
5335
+ display: flex;
5336
+ align-items: center;
5337
+ justify-content: center;
5338
+ border: none;
5339
+ border-radius: 50%;
5340
+ background: ${({ $accent }) => $accent};
5341
+ cursor: pointer;
5342
+ box-shadow:
5343
+ 0 8px 5px rgba(0, 0, 0, 0.1),
5344
+ 0 20px 12.5px rgba(0, 0, 0, 0.1);
5345
+ `;
5346
+ var SubButton = import_styled_components45.default.button`
5347
+ position: absolute;
5348
+ left: ${(FAB_SIZE - SUB_SIZE) / 2}px;
5349
+ top: ${(FAB_SIZE - SUB_SIZE) / 2}px;
5350
+ display: flex;
5351
+ align-items: center;
5352
+ justify-content: center;
5353
+ width: ${SUB_SIZE}px;
5354
+ height: ${SUB_SIZE}px;
5355
+ border: 1px solid ${colors.grey_300};
5356
+ border-radius: 50%;
5357
+ background: ${colors.white};
5358
+ cursor: pointer;
5359
+ box-shadow:
5360
+ 0 4px 3px rgba(0, 0, 0, 0.1),
5361
+ 0 10px 7.5px rgba(0, 0, 0, 0.1);
5362
+ transition:
5363
+ transform 0.2s ease,
5364
+ opacity 0.2s ease;
5365
+ transform: ${({ $isOpen, $transform }) => $isOpen ? $transform : "scale(0.4)"};
5366
+ opacity: ${({ $isOpen }) => $isOpen ? 1 : 0};
5367
+ pointer-events: ${({ $isOpen }) => $isOpen ? "auto" : "none"};
5368
+ `;
5369
+ var CountBadge = import_styled_components45.default.span`
5370
+ position: absolute;
5371
+ top: -4px;
5372
+ right: -4px;
5373
+ display: flex;
5374
+ align-items: center;
5375
+ justify-content: center;
5376
+ min-width: 18px;
5377
+ height: 18px;
5378
+ padding: 0 5px;
5379
+ border-radius: 9px;
5380
+ background: ${colors.red_950};
5381
+ color: ${colors.white};
5382
+ font-size: 11px;
5383
+ font-weight: 700;
5384
+ `;
5385
+
5386
+ // src/Components/ProgressBar/ProgressBar.tsx
5387
+ var import_styled_components46 = __toESM(require("styled-components"));
5388
+ var import_jsx_runtime57 = require("react/jsx-runtime");
5241
5389
  var clampPercent = (value) => Math.max(0, Math.min(100, value));
5242
- var Wrapper5 = import_styled_components45.default.div`
5390
+ var Wrapper5 = import_styled_components46.default.div`
5243
5391
  display: flex;
5244
5392
  align-items: center;
5245
5393
  gap: 8px;
5246
5394
  width: 100%;
5247
5395
  `;
5248
- var Track2 = import_styled_components45.default.div`
5396
+ var Track2 = import_styled_components46.default.div`
5249
5397
  position: relative;
5250
5398
  flex: 1;
5251
5399
  height: ${({ $height }) => $height}px;
@@ -5253,7 +5401,7 @@ var Track2 = import_styled_components45.default.div`
5253
5401
  border-radius: ${({ $height }) => $height}px;
5254
5402
  overflow: hidden;
5255
5403
  `;
5256
- var Fill = import_styled_components45.default.div`
5404
+ var Fill = import_styled_components46.default.div`
5257
5405
  height: 100%;
5258
5406
  width: ${({ $percent }) => $percent}%;
5259
5407
  background: ${({ $color }) => $color};
@@ -5268,9 +5416,9 @@ var ProgressBar = ({
5268
5416
  showLabel = false
5269
5417
  }) => {
5270
5418
  const percent = clampPercent(value);
5271
- return /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Wrapper5, { children: [
5272
- /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Track2, { $height: height, $trackColor: trackColor, children: /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(Fill, { $height: height, $color: color, $percent: percent }) }),
5273
- showLabel && /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(Text, { size: "s", weight: "600", children: [
5419
+ return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Wrapper5, { children: [
5420
+ /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Track2, { $height: height, $trackColor: trackColor, children: /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Fill, { $height: height, $color: color, $percent: percent }) }),
5421
+ showLabel && /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Text, { size: "s", weight: "600", children: [
5274
5422
  Math.round(percent),
5275
5423
  " %"
5276
5424
  ] })
@@ -5278,24 +5426,24 @@ var ProgressBar = ({
5278
5426
  };
5279
5427
 
5280
5428
  // src/Components/Timeline/Timeline.tsx
5281
- var import_styled_components46 = __toESM(require("styled-components"));
5282
- var import_jsx_runtime57 = require("react/jsx-runtime");
5283
- var List2 = import_styled_components46.default.div`
5429
+ var import_styled_components47 = __toESM(require("styled-components"));
5430
+ var import_jsx_runtime58 = require("react/jsx-runtime");
5431
+ var List2 = import_styled_components47.default.div`
5284
5432
  display: flex;
5285
5433
  flex-direction: column;
5286
5434
  `;
5287
- var Item2 = import_styled_components46.default.div`
5435
+ var Item2 = import_styled_components47.default.div`
5288
5436
  display: flex;
5289
5437
  gap: 12px;
5290
5438
  align-items: stretch;
5291
5439
  `;
5292
- var Rail = import_styled_components46.default.div`
5440
+ var Rail = import_styled_components47.default.div`
5293
5441
  display: flex;
5294
5442
  flex-direction: column;
5295
5443
  align-items: center;
5296
5444
  width: 16px;
5297
5445
  `;
5298
- var Dot2 = import_styled_components46.default.div`
5446
+ var Dot2 = import_styled_components47.default.div`
5299
5447
  width: 10px;
5300
5448
  height: 10px;
5301
5449
  border-radius: 50%;
@@ -5303,13 +5451,13 @@ var Dot2 = import_styled_components46.default.div`
5303
5451
  flex: 0 0 auto;
5304
5452
  background: ${({ $color }) => $color};
5305
5453
  `;
5306
- var Line = import_styled_components46.default.div`
5454
+ var Line = import_styled_components47.default.div`
5307
5455
  width: 2px;
5308
5456
  flex: 1;
5309
5457
  min-height: 16px;
5310
5458
  background: ${({ $color }) => $color};
5311
5459
  `;
5312
- var Content = import_styled_components46.default.div`
5460
+ var Content = import_styled_components47.default.div`
5313
5461
  display: flex;
5314
5462
  flex-direction: column;
5315
5463
  gap: 2px;
@@ -5321,30 +5469,30 @@ var Timeline = ({
5321
5469
  emptyLabel = "Aucun \xE9v\xE9nement"
5322
5470
  }) => {
5323
5471
  if (items.length === 0) {
5324
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Text, { size: "s", color: colors.grey_600, children: emptyLabel });
5472
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Text, { size: "s", color: colors.grey_600, children: emptyLabel });
5325
5473
  }
5326
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(List2, { children: items.map((item, index) => {
5474
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(List2, { children: items.map((item, index) => {
5327
5475
  var _a;
5328
5476
  const isLast = index === items.length - 1;
5329
5477
  const dotColor = (_a = item.color) != null ? _a : colors.blue_700;
5330
- return /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Item2, { children: [
5331
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Rail, { children: [
5332
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Dot2, { $color: dotColor }),
5333
- !isLast && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Line, { $color: lineColor })
5478
+ return /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Item2, { children: [
5479
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Rail, { children: [
5480
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Dot2, { $color: dotColor }),
5481
+ !isLast && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Line, { $color: lineColor })
5334
5482
  ] }),
5335
- /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(Content, { $last: isLast, children: [
5336
- /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Text, { size: "s", weight: item.highlighted ? "700" : "600", children: item.title }),
5337
- item.subtitle && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Text, { size: "xs", color: colors.grey_600, children: item.subtitle }),
5338
- item.description && /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(Text, { size: "xs", fontStyle: "italic", children: item.description })
5483
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsxs)(Content, { $last: isLast, children: [
5484
+ /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Text, { size: "s", weight: item.highlighted ? "700" : "600", children: item.title }),
5485
+ item.subtitle && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Text, { size: "xs", color: colors.grey_600, children: item.subtitle }),
5486
+ item.description && /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(Text, { size: "xs", fontStyle: "italic", children: item.description })
5339
5487
  ] })
5340
5488
  ] }, item.id);
5341
5489
  }) });
5342
5490
  };
5343
5491
 
5344
5492
  // src/Components/BorderedRow/BorderedRow.tsx
5345
- var import_styled_components47 = __toESM(require("styled-components"));
5346
- var import_jsx_runtime58 = require("react/jsx-runtime");
5347
- var Wrapper6 = import_styled_components47.default.div`
5493
+ var import_styled_components48 = __toESM(require("styled-components"));
5494
+ var import_jsx_runtime59 = require("react/jsx-runtime");
5495
+ var Wrapper6 = import_styled_components48.default.div`
5348
5496
  box-sizing: border-box;
5349
5497
  position: relative;
5350
5498
  width: 100%;
@@ -5380,7 +5528,7 @@ var BorderedRow = ({
5380
5528
  bordered = false,
5381
5529
  children,
5382
5530
  onClick
5383
- }) => /* @__PURE__ */ (0, import_jsx_runtime58.jsx)(
5531
+ }) => /* @__PURE__ */ (0, import_jsx_runtime59.jsx)(
5384
5532
  Wrapper6,
5385
5533
  {
5386
5534
  $borderColor: borderColor,
@@ -5658,6 +5806,7 @@ var optimizeImage_default = optimizeImage;
5658
5806
  Drawer,
5659
5807
  EmptyState,
5660
5808
  FileUploadZone,
5809
+ FloatingButton,
5661
5810
  Grid,
5662
5811
  Icon,
5663
5812
  IconTabs,
package/dist/index.mjs CHANGED
@@ -3808,6 +3808,10 @@ var TabButton = styled38.button.withConfig({
3808
3808
  shouldForwardProp: shouldForwardTab
3809
3809
  })`
3810
3810
  appearance: none;
3811
+ display: inline-flex;
3812
+ align-items: center;
3813
+ justify-content: center;
3814
+ gap: 6px;
3811
3815
  border: 0;
3812
3816
  background: ${(p) => {
3813
3817
  if (p.$variant !== "pills") return "transparent";
@@ -3849,6 +3853,14 @@ var TabButton = styled38.button.withConfig({
3849
3853
  opacity: 0.6;
3850
3854
  }
3851
3855
  `;
3856
+ var TabDot = styled38.span`
3857
+ display: inline-block;
3858
+ width: 8px;
3859
+ height: 8px;
3860
+ border-radius: 50%;
3861
+ flex: none;
3862
+ background: ${(p) => p.$color || colors.red_950};
3863
+ `;
3852
3864
  var Tab = (_a) => {
3853
3865
  var _b = _a, {
3854
3866
  id,
@@ -3939,7 +3951,7 @@ var Tabs = (_a) => {
3939
3951
  const isPillsFullWidth = variant === "pills" && align === "start";
3940
3952
  const rendered = useMemo(() => {
3941
3953
  if (items && items.length) {
3942
- return items.map((it) => /* @__PURE__ */ jsx45(
3954
+ return items.map((it) => /* @__PURE__ */ jsxs20(
3943
3955
  Tab,
3944
3956
  {
3945
3957
  id: it.id,
@@ -3949,7 +3961,10 @@ var Tabs = (_a) => {
3949
3961
  fullWidth: isPillsFullWidth,
3950
3962
  onClick: () => handleSelect(it.id),
3951
3963
  innerRef: setTabRef(it.id),
3952
- children: it.label
3964
+ children: [
3965
+ it.label,
3966
+ it.dot && /* @__PURE__ */ jsx45(TabDot, { $color: it.dotColor })
3967
+ ]
3953
3968
  },
3954
3969
  it.id
3955
3970
  ));
@@ -5158,17 +5173,149 @@ var EmptyState = ({
5158
5173
  );
5159
5174
  };
5160
5175
 
5161
- // src/Components/ProgressBar/ProgressBar.tsx
5176
+ // src/Components/FloatingButton/FloatingButton.tsx
5162
5177
  import styled45 from "styled-components";
5163
5178
  import { jsx as jsx56, jsxs as jsxs30 } from "react/jsx-runtime";
5179
+ var FloatingButton = ({
5180
+ isOpen,
5181
+ onToggle,
5182
+ actions,
5183
+ mainBadge = 0,
5184
+ label = "Menu",
5185
+ icon = "comment",
5186
+ openIcon = "xmark",
5187
+ variant = "blue_700"
5188
+ }) => {
5189
+ const accent = colors[variant];
5190
+ return /* @__PURE__ */ jsxs30(Container6, { children: [
5191
+ actions.map((action, index) => {
5192
+ var _a;
5193
+ return /* @__PURE__ */ jsxs30(
5194
+ SubButton,
5195
+ {
5196
+ type: "button",
5197
+ "aria-label": action.label,
5198
+ $isOpen: isOpen,
5199
+ $transform: arcTransform(index, actions.length),
5200
+ onClick: action.onClick,
5201
+ children: [
5202
+ /* @__PURE__ */ jsx56(Icon, { name: action.icon, family: "regular", size: "s", color: accent }),
5203
+ ((_a = action.badge) != null ? _a : 0) > 0 && /* @__PURE__ */ jsx56(CountBadge, { children: action.badge })
5204
+ ]
5205
+ },
5206
+ action.id
5207
+ );
5208
+ }),
5209
+ /* @__PURE__ */ jsxs30(
5210
+ MainButton,
5211
+ {
5212
+ type: "button",
5213
+ "aria-label": label,
5214
+ "aria-expanded": isOpen,
5215
+ $accent: accent,
5216
+ onClick: onToggle,
5217
+ children: [
5218
+ /* @__PURE__ */ jsx56(
5219
+ Icon,
5220
+ {
5221
+ name: isOpen ? openIcon : icon,
5222
+ family: "regular",
5223
+ size: "m",
5224
+ color: colors.white
5225
+ }
5226
+ ),
5227
+ !isOpen && mainBadge > 0 && /* @__PURE__ */ jsx56(CountBadge, { children: mainBadge })
5228
+ ]
5229
+ }
5230
+ )
5231
+ ] });
5232
+ };
5233
+ var FAB_SIZE = 56;
5234
+ var SUB_SIZE = 48;
5235
+ var ARC_RADIUS = 64;
5236
+ var ARC_START_ANGLE = 90;
5237
+ var ARC_MAX_STEP = 65;
5238
+ var ARC_MAX_SPAN = 90;
5239
+ var arcTransform = (index, total) => {
5240
+ const step = total > 1 ? Math.min(ARC_MAX_STEP, ARC_MAX_SPAN / (total - 1)) : 0;
5241
+ const angle = (ARC_START_ANGLE + index * step) * Math.PI / 180;
5242
+ const x = Math.round(Math.cos(angle) * ARC_RADIUS);
5243
+ const y = Math.round(-Math.sin(angle) * ARC_RADIUS);
5244
+ return `translate(${x}px, ${y}px)`;
5245
+ };
5246
+ var Container6 = styled45.div`
5247
+ position: fixed;
5248
+ right: 32px;
5249
+ bottom: 32px;
5250
+ width: ${FAB_SIZE}px;
5251
+ height: ${FAB_SIZE}px;
5252
+ z-index: 1000;
5253
+ `;
5254
+ var MainButton = styled45.button`
5255
+ position: absolute;
5256
+ inset: 0;
5257
+ display: flex;
5258
+ align-items: center;
5259
+ justify-content: center;
5260
+ border: none;
5261
+ border-radius: 50%;
5262
+ background: ${({ $accent }) => $accent};
5263
+ cursor: pointer;
5264
+ box-shadow:
5265
+ 0 8px 5px rgba(0, 0, 0, 0.1),
5266
+ 0 20px 12.5px rgba(0, 0, 0, 0.1);
5267
+ `;
5268
+ var SubButton = styled45.button`
5269
+ position: absolute;
5270
+ left: ${(FAB_SIZE - SUB_SIZE) / 2}px;
5271
+ top: ${(FAB_SIZE - SUB_SIZE) / 2}px;
5272
+ display: flex;
5273
+ align-items: center;
5274
+ justify-content: center;
5275
+ width: ${SUB_SIZE}px;
5276
+ height: ${SUB_SIZE}px;
5277
+ border: 1px solid ${colors.grey_300};
5278
+ border-radius: 50%;
5279
+ background: ${colors.white};
5280
+ cursor: pointer;
5281
+ box-shadow:
5282
+ 0 4px 3px rgba(0, 0, 0, 0.1),
5283
+ 0 10px 7.5px rgba(0, 0, 0, 0.1);
5284
+ transition:
5285
+ transform 0.2s ease,
5286
+ opacity 0.2s ease;
5287
+ transform: ${({ $isOpen, $transform }) => $isOpen ? $transform : "scale(0.4)"};
5288
+ opacity: ${({ $isOpen }) => $isOpen ? 1 : 0};
5289
+ pointer-events: ${({ $isOpen }) => $isOpen ? "auto" : "none"};
5290
+ `;
5291
+ var CountBadge = styled45.span`
5292
+ position: absolute;
5293
+ top: -4px;
5294
+ right: -4px;
5295
+ display: flex;
5296
+ align-items: center;
5297
+ justify-content: center;
5298
+ min-width: 18px;
5299
+ height: 18px;
5300
+ padding: 0 5px;
5301
+ border-radius: 9px;
5302
+ background: ${colors.red_950};
5303
+ color: ${colors.white};
5304
+ font-size: 11px;
5305
+ font-weight: 700;
5306
+ `;
5307
+
5308
+ // src/Components/ProgressBar/ProgressBar.tsx
5309
+ import styled46 from "styled-components";
5310
+ import { jsx as jsx57, jsxs as jsxs31 } from "react/jsx-runtime";
5164
5311
  var clampPercent = (value) => Math.max(0, Math.min(100, value));
5165
- var Wrapper5 = styled45.div`
5312
+ var Wrapper5 = styled46.div`
5166
5313
  display: flex;
5167
5314
  align-items: center;
5168
5315
  gap: 8px;
5169
5316
  width: 100%;
5170
5317
  `;
5171
- var Track2 = styled45.div`
5318
+ var Track2 = styled46.div`
5172
5319
  position: relative;
5173
5320
  flex: 1;
5174
5321
  height: ${({ $height }) => $height}px;
@@ -5176,7 +5323,7 @@ var Track2 = styled45.div`
5176
5323
  border-radius: ${({ $height }) => $height}px;
5177
5324
  overflow: hidden;
5178
5325
  `;
5179
- var Fill = styled45.div`
5326
+ var Fill = styled46.div`
5180
5327
  height: 100%;
5181
5328
  width: ${({ $percent }) => $percent}%;
5182
5329
  background: ${({ $color }) => $color};
@@ -5191,9 +5338,9 @@ var ProgressBar = ({
5191
5338
  showLabel = false
5192
5339
  }) => {
5193
5340
  const percent = clampPercent(value);
5194
- return /* @__PURE__ */ jsxs30(Wrapper5, { children: [
5195
- /* @__PURE__ */ jsx56(Track2, { $height: height, $trackColor: trackColor, children: /* @__PURE__ */ jsx56(Fill, { $height: height, $color: color, $percent: percent }) }),
5196
- showLabel && /* @__PURE__ */ jsxs30(Text, { size: "s", weight: "600", children: [
5341
+ return /* @__PURE__ */ jsxs31(Wrapper5, { children: [
5342
+ /* @__PURE__ */ jsx57(Track2, { $height: height, $trackColor: trackColor, children: /* @__PURE__ */ jsx57(Fill, { $height: height, $color: color, $percent: percent }) }),
5343
+ showLabel && /* @__PURE__ */ jsxs31(Text, { size: "s", weight: "600", children: [
5197
5344
  Math.round(percent),
5198
5345
  " %"
5199
5346
  ] })
@@ -5201,24 +5348,24 @@ var ProgressBar = ({
5201
5348
  };
5202
5349
 
5203
5350
  // src/Components/Timeline/Timeline.tsx
5204
- import styled46 from "styled-components";
5205
- import { jsx as jsx57, jsxs as jsxs31 } from "react/jsx-runtime";
5206
- var List2 = styled46.div`
5351
+ import styled47 from "styled-components";
5352
+ import { jsx as jsx58, jsxs as jsxs32 } from "react/jsx-runtime";
5353
+ var List2 = styled47.div`
5207
5354
  display: flex;
5208
5355
  flex-direction: column;
5209
5356
  `;
5210
- var Item2 = styled46.div`
5357
+ var Item2 = styled47.div`
5211
5358
  display: flex;
5212
5359
  gap: 12px;
5213
5360
  align-items: stretch;
5214
5361
  `;
5215
- var Rail = styled46.div`
5362
+ var Rail = styled47.div`
5216
5363
  display: flex;
5217
5364
  flex-direction: column;
5218
5365
  align-items: center;
5219
5366
  width: 16px;
5220
5367
  `;
5221
- var Dot2 = styled46.div`
5368
+ var Dot2 = styled47.div`
5222
5369
  width: 10px;
5223
5370
  height: 10px;
5224
5371
  border-radius: 50%;
@@ -5226,13 +5373,13 @@ var Dot2 = styled46.div`
5226
5373
  flex: 0 0 auto;
5227
5374
  background: ${({ $color }) => $color};
5228
5375
  `;
5229
- var Line = styled46.div`
5376
+ var Line = styled47.div`
5230
5377
  width: 2px;
5231
5378
  flex: 1;
5232
5379
  min-height: 16px;
5233
5380
  background: ${({ $color }) => $color};
5234
5381
  `;
5235
- var Content = styled46.div`
5382
+ var Content = styled47.div`
5236
5383
  display: flex;
5237
5384
  flex-direction: column;
5238
5385
  gap: 2px;
@@ -5244,30 +5391,30 @@ var Timeline = ({
5244
5391
  emptyLabel = "Aucun \xE9v\xE9nement"
5245
5392
  }) => {
5246
5393
  if (items.length === 0) {
5247
- return /* @__PURE__ */ jsx57(Text, { size: "s", color: colors.grey_600, children: emptyLabel });
5394
+ return /* @__PURE__ */ jsx58(Text, { size: "s", color: colors.grey_600, children: emptyLabel });
5248
5395
  }
5249
- return /* @__PURE__ */ jsx57(List2, { children: items.map((item, index) => {
5396
+ return /* @__PURE__ */ jsx58(List2, { children: items.map((item, index) => {
5250
5397
  var _a;
5251
5398
  const isLast = index === items.length - 1;
5252
5399
  const dotColor = (_a = item.color) != null ? _a : colors.blue_700;
5253
- return /* @__PURE__ */ jsxs31(Item2, { children: [
5254
- /* @__PURE__ */ jsxs31(Rail, { children: [
5255
- /* @__PURE__ */ jsx57(Dot2, { $color: dotColor }),
5256
- !isLast && /* @__PURE__ */ jsx57(Line, { $color: lineColor })
5400
+ return /* @__PURE__ */ jsxs32(Item2, { children: [
5401
+ /* @__PURE__ */ jsxs32(Rail, { children: [
5402
+ /* @__PURE__ */ jsx58(Dot2, { $color: dotColor }),
5403
+ !isLast && /* @__PURE__ */ jsx58(Line, { $color: lineColor })
5257
5404
  ] }),
5258
- /* @__PURE__ */ jsxs31(Content, { $last: isLast, children: [
5259
- /* @__PURE__ */ jsx57(Text, { size: "s", weight: item.highlighted ? "700" : "600", children: item.title }),
5260
- item.subtitle && /* @__PURE__ */ jsx57(Text, { size: "xs", color: colors.grey_600, children: item.subtitle }),
5261
- item.description && /* @__PURE__ */ jsx57(Text, { size: "xs", fontStyle: "italic", children: item.description })
5405
+ /* @__PURE__ */ jsxs32(Content, { $last: isLast, children: [
5406
+ /* @__PURE__ */ jsx58(Text, { size: "s", weight: item.highlighted ? "700" : "600", children: item.title }),
5407
+ item.subtitle && /* @__PURE__ */ jsx58(Text, { size: "xs", color: colors.grey_600, children: item.subtitle }),
5408
+ item.description && /* @__PURE__ */ jsx58(Text, { size: "xs", fontStyle: "italic", children: item.description })
5262
5409
  ] })
5263
5410
  ] }, item.id);
5264
5411
  }) });
5265
5412
  };
5266
5413
 
5267
5414
  // src/Components/BorderedRow/BorderedRow.tsx
5268
- import styled47 from "styled-components";
5269
- import { jsx as jsx58 } from "react/jsx-runtime";
5270
- var Wrapper6 = styled47.div`
5415
+ import styled48 from "styled-components";
5416
+ import { jsx as jsx59 } from "react/jsx-runtime";
5417
+ var Wrapper6 = styled48.div`
5271
5418
  box-sizing: border-box;
5272
5419
  position: relative;
5273
5420
  width: 100%;
@@ -5303,7 +5450,7 @@ var BorderedRow = ({
5303
5450
  bordered = false,
5304
5451
  children,
5305
5452
  onClick
5306
- }) => /* @__PURE__ */ jsx58(
5453
+ }) => /* @__PURE__ */ jsx59(
5307
5454
  Wrapper6,
5308
5455
  {
5309
5456
  $borderColor: borderColor,
@@ -5580,6 +5727,7 @@ export {
5580
5727
  Drawer,
5581
5728
  EmptyState,
5582
5729
  FileUploadZone,
5730
+ FloatingButton,
5583
5731
  Grid,
5584
5732
  Icon,
5585
5733
  IconTabs,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "design-zystem",
3
- "version": "1.0.250",
3
+ "version": "1.0.252",
4
4
  "description": "A React design system of importable components",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",