@flikk/ui 1.0.0-beta.24 → 1.0.0-beta.26

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.
Files changed (135) hide show
  1. package/dist/components/ai/CodeBlock/CodeBlock.theme.js +2 -2
  2. package/dist/components/ai/PromptInput/PromptInput.js +1 -0
  3. package/dist/components/ai/PromptInput/VoiceRecorder.js +1 -0
  4. package/dist/components/ai/StreamingResponse/MarkdownRenderer.js +1 -1
  5. package/dist/components/ai/TokenCounter/TokenCounter.theme.js +1 -1
  6. package/dist/components/charts/BarChart/BarChart.js +2 -2
  7. package/dist/components/charts/StackedBarChart/StackedBarChart.js +1 -1
  8. package/dist/components/charts/shared/BarRenderer/BarRenderer.js +2 -2
  9. package/dist/components/core/Accordion/Accordion.theme.js +2 -2
  10. package/dist/components/core/Breadcrumbs/Breadcrumbs.js +1 -1
  11. package/dist/components/core/Breadcrumbs/Breadcrumbs.theme.js +2 -2
  12. package/dist/components/core/Button/Button.js +1 -1
  13. package/dist/components/core/Button/Button.theme.js +4 -4
  14. package/dist/components/core/Calendar/Calendar.js +1 -1
  15. package/dist/components/core/Calendar/CalendarMini/CalendarMini.js +4 -2
  16. package/dist/components/core/Calendar/CalendarMini/CalendarMini.theme.js +2 -2
  17. package/dist/components/core/ContextMenu/ContextMenu.theme.js +1 -1
  18. package/dist/components/core/Drawer/Drawer.theme.js +2 -2
  19. package/dist/components/core/Dropdown/Dropdown.theme.js +2 -2
  20. package/dist/components/core/Empty/Empty.js +1 -1
  21. package/dist/components/core/Empty/Empty.theme.js +1 -1
  22. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.d.ts +14 -0
  23. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.js +28 -0
  24. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.d.ts +6 -0
  25. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.theme.js +8 -0
  26. package/dist/components/core/ImagePlaceholder/ImagePlaceholder.types.d.ts +32 -0
  27. package/dist/components/core/ImagePlaceholder/index.d.ts +2 -0
  28. package/dist/components/core/Link/Link.js +1 -1
  29. package/dist/components/core/Message/Message.theme.js +1 -1
  30. package/dist/components/core/Modal/Modal.theme.js +1 -1
  31. package/dist/components/core/NavItem/NavItem.d.ts +1 -1
  32. package/dist/components/core/NavItem/NavItem.js +171 -68
  33. package/dist/components/core/NavItem/NavItem.theme.js +20 -12
  34. package/dist/components/core/NavItem/NavItem.types.d.ts +17 -39
  35. package/dist/components/core/Pagination/Pagination.theme.js +3 -3
  36. package/dist/components/core/Popover/Popover.theme.js +1 -1
  37. package/dist/components/core/Progress/Progress.theme.js +1 -1
  38. package/dist/components/core/ScrollArea/ScrollArea.js +2 -2
  39. package/dist/components/core/ScrollArea/ScrollArea.theme.js +1 -1
  40. package/dist/components/core/Segmented/Segmented.js +8 -6
  41. package/dist/components/core/Segmented/Segmented.theme.js +3 -3
  42. package/dist/components/core/Sidebar/Sidebar.d.ts +1 -1
  43. package/dist/components/core/Sidebar/Sidebar.js +42 -13
  44. package/dist/components/core/Sidebar/Sidebar.theme.js +5 -7
  45. package/dist/components/core/Sidebar/Sidebar.types.d.ts +33 -4
  46. package/dist/components/core/Sidebar/SidebarContent.js +6 -6
  47. package/dist/components/core/Sidebar/SidebarContext.d.ts +17 -16
  48. package/dist/components/core/Sidebar/SidebarContext.js +42 -19
  49. package/dist/components/core/Sidebar/SidebarFooter.js +4 -6
  50. package/dist/components/core/Sidebar/SidebarHeader.js +4 -9
  51. package/dist/components/core/Sidebar/SidebarLogo.js +3 -7
  52. package/dist/components/core/Sidebar/SidebarNav.js +4 -3
  53. package/dist/components/core/Sidebar/SidebarNavGroup.js +4 -7
  54. package/dist/components/core/Sidebar/SidebarToggle.js +6 -1
  55. package/dist/components/core/Sidebar/SidebarUserProfile.js +33 -17
  56. package/dist/components/core/Sidebar/index.d.ts +2 -3
  57. package/dist/components/core/Skeleton/Skeleton.theme.js +1 -1
  58. package/dist/components/core/Spinner/Spinner.theme.js +1 -1
  59. package/dist/components/core/Tabs/Tabs.js +6 -1
  60. package/dist/components/core/Tabs/Tabs.types.d.ts +2 -0
  61. package/dist/components/core/Tabs/TabsBody.js +5 -3
  62. package/dist/components/core/Tag/Tag.theme.js +1 -1
  63. package/dist/components/core/index.d.ts +1 -0
  64. package/dist/components/core/index.js +2 -2
  65. package/dist/components/data-display/GanttChart/GanttTableGroupRow.js +1 -1
  66. package/dist/components/data-display/KPI/KPI.js +13 -3
  67. package/dist/components/data-display/KPI/KPI.theme.js +3 -3
  68. package/dist/components/data-display/Metric/Metric.theme.js +3 -3
  69. package/dist/components/data-display/Table/Table.js +4 -3
  70. package/dist/components/data-display/Table/Table.theme.js +11 -1
  71. package/dist/components/data-display/Table/Table.types.d.ts +15 -0
  72. package/dist/components/data-display/Table/TableColumnManager.js +1 -1
  73. package/dist/components/data-display/Table/index.d.ts +2 -2
  74. package/dist/components/data-display/Timeline/Timeline.animations.d.ts +0 -7
  75. package/dist/components/data-display/Timeline/Timeline.animations.js +1 -27
  76. package/dist/components/data-display/Timeline/Timeline.js +3 -4
  77. package/dist/components/data-display/Timeline/Timeline.types.d.ts +0 -13
  78. package/dist/components/data-display/Timeline/TimelineContent.js +3 -7
  79. package/dist/components/data-display/Timeline/TimelineItem.js +4 -17
  80. package/dist/components/data-display/Timeline/index.d.ts +2 -2
  81. package/dist/components/effects/Aurora/Aurora.js +79 -40
  82. package/dist/components/effects/InteractiveCharacters/InteractiveCharacters.js +3 -3
  83. package/dist/components/effects/InteractiveCharacters/characters/BlobCharacter.js +13 -4
  84. package/dist/components/effects/InteractiveCharacters/characters/SmallCharacter.js +13 -4
  85. package/dist/components/effects/InteractiveCharacters/characters/TallCharacter.js +14 -4
  86. package/dist/components/effects/MorphingText/MorphingText.js +40 -7
  87. package/dist/components/effects/StripePattern/StripePattern.d.ts +18 -0
  88. package/dist/components/effects/StripePattern/StripePattern.js +54 -0
  89. package/dist/components/effects/StripePattern/StripePattern.types.d.ts +53 -0
  90. package/dist/components/effects/StripePattern/index.d.ts +2 -0
  91. package/dist/components/effects/index.d.ts +9 -0
  92. package/dist/components/effects/index.js +4 -0
  93. package/dist/components/forms/Checkbox/Checkbox.theme.js +1 -1
  94. package/dist/components/forms/CronInput/CronInput.theme.js +16 -16
  95. package/dist/components/forms/DatePicker/DatePickerTrigger.js +1 -1
  96. package/dist/components/forms/DateRangePicker/DateRangePicker.theme.js +1 -1
  97. package/dist/components/forms/DateRangePicker/DateRangePickerTrigger.js +1 -1
  98. package/dist/components/forms/FileUpload/FileUpload.js +1 -1
  99. package/dist/components/forms/FileUpload/FileUploadProgress.js +27 -20
  100. package/dist/components/forms/FileUpload/FileUploadProgress.theme.js +2 -2
  101. package/dist/components/forms/Input/Input.theme.js +9 -11
  102. package/dist/components/forms/Mention/Mention.theme.js +3 -3
  103. package/dist/components/forms/Radio/Radio.theme.js +1 -1
  104. package/dist/components/forms/RichTextEditor/RichTextEditor.d.ts +18 -0
  105. package/dist/components/forms/RichTextEditor/RichTextEditor.js +1231 -236
  106. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.d.ts +53 -1
  107. package/dist/components/forms/RichTextEditor/RichTextEditor.theme.js +99 -25
  108. package/dist/components/forms/RichTextEditor/RichTextEditor.types.d.ts +42 -3
  109. package/dist/components/forms/RichTextEditor/index.d.ts +2 -2
  110. package/dist/components/forms/Select/Select.js +2 -2
  111. package/dist/components/forms/Slider/Slider.theme.js +1 -1
  112. package/dist/components/forms/Switch/Switch.theme.js +1 -1
  113. package/dist/components/forms/TimePicker/TimePicker.theme.js +2 -2
  114. package/dist/components/forms/TimePicker/TimePickerContent.js +1 -0
  115. package/dist/components/forms/TimePicker/TimePickerTrigger.js +1 -1
  116. package/dist/components/forms/forms.theme.js +12 -12
  117. package/dist/components/forms/index.js +1 -0
  118. package/dist/components/layout/FormLayout/FormLayout.js +6 -4
  119. package/dist/components/layout/FormLayout/FormLayout.types.d.ts +3 -3
  120. package/dist/components/layout/FormLayout/FormLayoutSection.js +6 -1
  121. package/dist/components/layout/PageLayout/PageLayout.d.ts +2 -2
  122. package/dist/components/layout/PageLayout/PageLayout.js +23 -5
  123. package/dist/components/layout/PageLayout/PageLayout.theme.d.ts +2 -1
  124. package/dist/components/layout/PageLayout/PageLayout.theme.js +35 -6
  125. package/dist/components/layout/PageLayout/PageLayout.types.d.ts +45 -0
  126. package/dist/components/layout/PageLayout/PageLayoutContent.js +6 -4
  127. package/dist/components/layout/PageLayout/PageLayoutHeader.js +3 -3
  128. package/dist/components/layout/PageLayout/PageLayoutSidebar.js +5 -3
  129. package/dist/components/layout/PageLayout/index.d.ts +1 -1
  130. package/dist/index.js +2 -2
  131. package/dist/styles.css +1 -1
  132. package/package.json +1 -1
  133. package/src/styles/theme.css +127 -92
  134. package/dist/components/core/Sidebar/SidebarSubmenu.d.ts +0 -7
  135. package/dist/components/core/Sidebar/SidebarSubmenu.js +0 -12
@@ -16,13 +16,13 @@ const cronInputTheme = {
16
16
  // Field label
17
17
  fieldLabelStyle: "text-xs font-medium text-[var(--color-text-secondary)] dark:text-[var(--color-neutral-400)]",
18
18
  // Select dropdown
19
- fieldSelectStyle: "w-full rounded-[var(--form-radius)] outline outline-1 outline-[var(--color-border)] " +
19
+ fieldSelectStyle: "w-full rounded-[var(--form-radius)] outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
20
20
  "bg-white text-[var(--color-text-primary)] cursor-pointer transition-all " +
21
- "focus:outline-2 focus:outline-[var(--color-primary-600)] focus:-outline-offset-1 " +
21
+ "focus:shadow-[inset_0_0_0_2px_var(--color-primary-600)] " +
22
22
  "focus:ring-4 focus:ring-[var(--color-primary)]/10 " +
23
23
  "disabled:cursor-not-allowed disabled:bg-[var(--color-background-disabled)] disabled:text-[var(--color-text-disabled)] " +
24
- "dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)] dark:text-[var(--color-neutral-200)] " +
25
- "dark:focus:outline-[var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
24
+ "dark:bg-[var(--color-neutral-900)] dark:shadow-[inset_0_0_0_1px_var(--color-neutral-700)] dark:text-[var(--color-neutral-200)] " +
25
+ "dark:focus:shadow-[inset_0_0_0_2px_var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
26
26
  // Size variants for field selects
27
27
  fieldSelectSizes: {
28
28
  sm: `${formsBaseTheme.sizes.sm.text} ${formsBaseTheme.sizes.sm.padding} ${formsBaseTheme.sizes.sm.height}`,
@@ -30,14 +30,14 @@ const cronInputTheme = {
30
30
  lg: `${formsBaseTheme.sizes.lg.text} ${formsBaseTheme.sizes.lg.padding} ${formsBaseTheme.sizes.lg.height}`,
31
31
  },
32
32
  // Raw input field
33
- rawInputStyle: "w-full rounded-[var(--form-radius)] outline outline-1 outline-[var(--color-border)] " +
33
+ rawInputStyle: "w-full rounded-[var(--form-radius)] outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
34
34
  "bg-white text-[var(--color-text-primary)] font-mono transition-all " +
35
35
  "placeholder:text-[var(--color-text-placeholder)] focus:outline-none " +
36
- "focus:outline-2 focus:outline-[var(--color-primary-600)] focus:-outline-offset-1 " +
36
+ "focus:shadow-[inset_0_0_0_2px_var(--color-primary-600)] " +
37
37
  "focus:ring-4 focus:ring-[var(--color-primary)]/10 " +
38
38
  "disabled:cursor-not-allowed disabled:bg-[var(--color-background-disabled)] disabled:text-[var(--color-text-disabled)] " +
39
- "dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)] dark:text-[var(--color-neutral-200)] " +
40
- "dark:focus:outline-[var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
39
+ "dark:bg-[var(--color-neutral-900)] dark:shadow-[inset_0_0_0_1px_var(--color-neutral-700)] dark:text-[var(--color-neutral-200)] " +
40
+ "dark:focus:shadow-[inset_0_0_0_2px_var(--color-primary-500)] dark:focus:ring-[var(--color-primary-500)]/20",
41
41
  // Size variants for raw input
42
42
  rawInputSizes: {
43
43
  sm: `${formsBaseTheme.sizes.sm.text} ${formsBaseTheme.sizes.sm.padding} ${formsBaseTheme.sizes.sm.height}`,
@@ -46,26 +46,26 @@ const cronInputTheme = {
46
46
  },
47
47
  // Mode toggle button
48
48
  modeToggleStyle: "inline-flex items-center justify-center rounded-[var(--form-radius)] px-3 py-1.5 text-xs font-medium " +
49
- "cursor-pointer transition-all outline outline-1 outline-[var(--color-border)] " +
49
+ "cursor-pointer transition-all outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
50
50
  "text-[var(--color-text-secondary)] bg-white hover:bg-[var(--color-background-secondary)] " +
51
- "dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)] dark:text-[var(--color-neutral-400)] " +
51
+ "dark:bg-[var(--color-neutral-900)] dark:shadow-[inset_0_0_0_1px_var(--color-neutral-700)] dark:text-[var(--color-neutral-400)] " +
52
52
  "dark:hover:bg-[var(--color-neutral-800)]",
53
53
  // Active mode toggle
54
- modeToggleActiveStyle: "outline-[var(--color-primary)] bg-[var(--color-primary-50)] text-[var(--color-primary)] " +
54
+ modeToggleActiveStyle: "shadow-[inset_0_0_0_1px_var(--color-primary)] bg-[var(--color-primary-50)] text-[var(--color-primary)] " +
55
55
  "hover:bg-[var(--color-primary-50)] " +
56
- "dark:outline-[var(--color-primary-500)] dark:bg-[var(--color-primary-500)]/10 dark:text-[var(--color-primary-400)] " +
56
+ "dark:shadow-[inset_0_0_0_1px_var(--color-primary-500)] dark:bg-[var(--color-primary-500)]/10 dark:text-[var(--color-primary-400)] " +
57
57
  "dark:hover:bg-[var(--color-primary-500)]/15",
58
58
  // Preset button
59
59
  presetButtonStyle: "inline-flex items-center rounded-[var(--form-radius)] px-2.5 py-1 text-xs font-medium " +
60
- "cursor-pointer transition-all outline outline-1 outline-[var(--color-border)] " +
60
+ "cursor-pointer transition-all outline-none shadow-[inset_0_0_0_1px_var(--color-border)] " +
61
61
  "text-[var(--color-text-secondary)] bg-white hover:bg-[var(--color-background-secondary)] " +
62
62
  "hover:text-[var(--color-text-primary)] " +
63
- "dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)] dark:text-[var(--color-neutral-400)] " +
63
+ "dark:bg-[var(--color-neutral-900)] dark:shadow-[inset_0_0_0_1px_var(--color-neutral-700)] dark:text-[var(--color-neutral-400)] " +
64
64
  "dark:hover:bg-[var(--color-neutral-800)] dark:hover:text-[var(--color-neutral-200)]",
65
65
  // Active preset button
66
- presetButtonActiveStyle: "outline-[var(--color-primary)] bg-[var(--color-primary-50)] text-[var(--color-primary)] " +
66
+ presetButtonActiveStyle: "shadow-[inset_0_0_0_1px_var(--color-primary)] bg-[var(--color-primary-50)] text-[var(--color-primary)] " +
67
67
  "hover:bg-[var(--color-primary-100)] " +
68
- "dark:outline-[var(--color-primary-500)] dark:bg-[var(--color-primary-500)]/10 dark:text-[var(--color-primary-400)]",
68
+ "dark:shadow-[inset_0_0_0_1px_var(--color-primary-500)] dark:bg-[var(--color-primary-500)]/10 dark:text-[var(--color-primary-400)]",
69
69
  // Human-readable description
70
70
  descriptionStyle: "flex items-center gap-2 text-sm text-[var(--color-text-muted)] " +
71
71
  "dark:text-[var(--color-neutral-400)]",
@@ -26,7 +26,7 @@ const DatePickerTrigger = ({ id, disabled, isOpen, state = "default", size = "md
26
26
  // Apply focused styles when open - same pattern as SelectButton
27
27
  const activeFocusState = isOpen
28
28
  ? focusStateStyle ||
29
- "outline-2 outline-primary-600 -outline-offset-1 ring-4 ring-[var(--color-primary)]/10"
29
+ "shadow-[inset_0_0_0_2px_var(--color-primary-600)] ring-4 ring-[var(--color-primary)]/10"
30
30
  : "";
31
31
  return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open calendar", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(CalendarIcon, { className: "h-4 w-4" }) })] }) }));
32
32
  };
@@ -35,7 +35,7 @@ const dateRangePickerTheme = {
35
35
  mobilePresetsContainerStyle: "sm:hidden px-3 pt-3 pb-1",
36
36
  mobilePresetButtonStyle: "whitespace-nowrap px-3 py-1.5 text-xs font-medium rounded-full transition-colors cursor-pointer shrink-0 " +
37
37
  "bg-[var(--color-background-secondary)] text-[var(--color-text-secondary)] " +
38
- "hover:bg-[var(--color-background-tertiary)] hover:text-[var(--color-text-primary)] " +
38
+ "hover:bg-[var(--color-surface-hover)] hover:text-[var(--color-text-primary)] " +
39
39
  "data-[active=true]:bg-[var(--color-primary-50)] data-[active=true]:text-[var(--color-primary)] " +
40
40
  "dark:bg-[var(--color-neutral-800)] dark:text-[var(--color-neutral-300)] " +
41
41
  "dark:hover:bg-[var(--color-neutral-700)] " +
@@ -24,7 +24,7 @@ const DateRangePickerTrigger = ({ id, disabled, isOpen, state = "default", size
24
24
  const triggerButtonStyle = theme.triggerButtonStyle || "";
25
25
  const activeFocusState = isOpen
26
26
  ? focusStateStyle ||
27
- "outline-2 outline-primary-600 -outline-offset-1 ring-4 ring-[var(--color-primary)]/10"
27
+ "shadow-[inset_0_0_0_2px_var(--color-primary-600)] ring-4 ring-[var(--color-primary)]/10"
28
28
  : "";
29
29
  return (jsx("div", { className: "relative w-full", children: jsxs("button", { ref: triggerRef, id: id, type: "button", className: cn(baseStyle, sizeStyle, stateStyle, hoverStateStyle, activeFocusState, iconEndPadding, triggerButtonStyle, "text-left", className), onClick: onClick, onFocus: onFocus, onBlur: onBlur, disabled: disabled, "aria-expanded": isOpen, "aria-haspopup": "dialog", "aria-label": "Open date range picker", "aria-invalid": ariaInvalid, "aria-describedby": ariaDescribedby, children: [children, jsx("span", { className: iconEndStyle, children: jsx(CalendarIcon, { className: "h-4 w-4" }) })] }) }));
30
30
  };
@@ -78,7 +78,6 @@ import '../../core/Sidebar/SidebarContent.js';
78
78
  import '../../core/Sidebar/SidebarFooter.js';
79
79
  import '../../core/Sidebar/SidebarNav.js';
80
80
  import '../../core/Sidebar/SidebarNavGroup.js';
81
- import 'motion/react';
82
81
  import '../../core/Sidebar/SidebarToggle.js';
83
82
  import '../../core/Sidebar/SidebarMobileTrigger.js';
84
83
  import '../../core/Sidebar/SidebarUserProfile.js';
@@ -89,6 +88,7 @@ import '../../core/ContextMenu/ContextMenu.js';
89
88
  import '../../core/ContextMenu/ContextMenu.theme.js';
90
89
  import '../../core/Pill/Pill.js';
91
90
  import '../../core/Icon/Icon.js';
91
+ import '../../core/ImagePlaceholder/ImagePlaceholder.js';
92
92
  import { FormLabel } from '../FormLabel/FormLabel.js';
93
93
 
94
94
  /**
@@ -1,7 +1,7 @@
1
1
  import { jsx, jsxs } from 'react/jsx-runtime';
2
2
  import React__default, { useState, useEffect } from 'react';
3
3
  import { useReducedMotion, motion, AnimatePresence } from 'motion/react';
4
- import { DocumentIcon, TrashIcon, XMarkIcon, ArrowPathIcon } from '@heroicons/react/24/outline';
4
+ import { DocumentIcon, TrashIcon, ArrowPathIcon, XMarkIcon } from '@heroicons/react/24/outline';
5
5
  import { Icon } from '../../core/Icon/Icon.js';
6
6
  import { fileTypes } from '../../core/Icon/data/fileTypes.js';
7
7
  import { cn } from '../../../utils/cn.js';
@@ -39,27 +39,38 @@ const RadialProgress = ({ progress, status, strokeWidth, trackColor, progressCol
39
39
  setShowRemove(false);
40
40
  }, [isComplete, completionDelay]);
41
41
  const handleClick = () => {
42
- if (isError && onRetry) {
43
- onRetry();
42
+ if (!onRemove)
44
43
  return;
44
+ if (confirmRemove) {
45
+ setConfirmOpen(true);
45
46
  }
46
- if (onRemove) {
47
- if (confirmRemove) {
48
- setConfirmOpen(true);
49
- }
50
- else {
51
- onRemove();
52
- }
47
+ else {
48
+ onRemove();
53
49
  }
54
50
  };
55
51
  const handleConfirm = () => {
56
52
  setConfirmOpen(false);
57
53
  onRemove === null || onRemove === void 0 ? void 0 : onRemove();
58
54
  };
59
- const isClickable = (isError && onRetry) || onRemove;
60
- const ariaLabel = isError && onRetry ? "Retry upload" : onRemove ? "Remove file" : undefined;
55
+ // Uploading/complete: the radial doubles as the cancel/remove target.
56
+ const isClickable = !!onRemove;
57
+ const ariaLabel = onRemove ? "Remove file" : undefined;
58
+ // Confirm popover shared by the radial (cancel/remove) and the error-state delete button.
59
+ const confirmPopover = (trigger, label, offsetValue) => (jsxs(Popover, { isOpen: confirmOpen, onOpenChange: (open) => {
60
+ setConfirmOpen(open);
61
+ if (!open)
62
+ setIsHovered(false);
63
+ }, placement: "bottom-end", offset: offsetValue, triggerType: "click", children: [jsx(Popover.Trigger, { children: trigger }), jsxs(Popover.Body, { className: "flex items-center p-1 border-[0.5px] rounded-xl gap-0.5 bg-opacity-50 backdrop-blur-md", children: [jsx("span", { className: "text-sm font-semibold text-[var(--color-text-secondary)] px-3", children: label }), jsxs("div", { className: "flex gap-1", children: [jsx(Button, { size: "sm", color: "danger", variant: "filled", onClick: handleConfirm, children: "Yes" }), jsx(Button, { size: "sm", variant: "soft", color: "neutral", onClick: () => setConfirmOpen(false), children: "No" })] })] })] }));
61
64
  // Shared remove button used after completion tick
62
65
  const removeButton = (jsx(motion.div, { initial: shouldReduceMotion ? false : REMOVE_BUTTON_ENTER.initial, animate: REMOVE_BUTTON_ENTER.animate, transition: REMOVE_BUTTON_ENTER.transition, className: "shrink-0", children: jsx(Button, { size: "sm", variant: "soft", color: "neutral", "aria-label": "Remove file", iconOnly: true, className: "rounded-full size-8", onClick: confirmRemove ? undefined : () => onRemove === null || onRemove === void 0 ? void 0 : onRemove(), children: jsx(TrashIcon, { className: "size-3.5", strokeWidth: 2 }) }) }, "remove-btn"));
66
+ // Error state: retry + delete buttons (no progress arc/percentage).
67
+ if (isError) {
68
+ const deleteButton = onRemove ? (jsx(Button, { size: "sm", variant: "soft", color: "neutral", "aria-label": "Remove file", iconOnly: true, className: "rounded-full size-8", onClick: confirmRemove ? undefined : () => onRemove(), children: jsx(TrashIcon, { className: "size-3.5", strokeWidth: 2 }) })) : null;
69
+ return (jsxs("div", { className: "flex items-center gap-1 shrink-0", children: [onRetry && (jsx(Button, { size: "sm", variant: "soft", color: "neutral", "aria-label": "Retry upload", iconOnly: true, className: "rounded-full size-8", onClick: () => onRetry(), children: jsx(ArrowPathIcon, { className: "size-3.5", strokeWidth: 2 }) })), deleteButton &&
70
+ (confirmRemove
71
+ ? confirmPopover(deleteButton, "Remove file?", 6)
72
+ : deleteButton)] }));
73
+ }
63
74
  const radialElement = (jsxs("div", { className: cn("relative shrink-0", sizeClass, isClickable && "cursor-pointer"), onMouseEnter: () => setIsHovered(true), onMouseLeave: () => {
64
75
  if (!confirmOpen)
65
76
  setIsHovered(false);
@@ -70,18 +81,14 @@ const RadialProgress = ({ progress, status, strokeWidth, trackColor, progressCol
70
81
  handleClick();
71
82
  }
72
83
  }
73
- : undefined, children: [jsxs("svg", { viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`, className: "w-full h-full -rotate-90", children: [jsx("circle", { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: trackColor, strokeWidth: strokeWidth }), jsx(motion.circle, { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: progressColor, strokeWidth: strokeWidth, strokeLinecap: "round", strokeDasharray: circumference, initial: { strokeDashoffset: circumference }, animate: { strokeDashoffset: isComplete ? 0 : offset }, transition: shouldReduceMotion ? { duration: 0 } : PROGRESS_SPRING })] }), jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsxs(AnimatePresence, { mode: "wait", initial: false, children: [isUploading && !isHovered && (jsx(motion.span, { className: centerTextStyle, ...(shouldReduceMotion ? {} : CROSSFADE), children: progress }, "percent")), isUploading && isHovered && onRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(XMarkIcon, { className: "size-4 text-[var(--color-text-muted)]", strokeWidth: 2.5 }) }, "close")), isComplete && !showRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx("svg", { viewBox: "0 0 24 24", fill: "none", className: cn("size-4", statusIconColor), children: jsx("path", { d: "M5 13l4.5 4.5L19 7", stroke: "currentColor", strokeWidth: 3.5, strokeLinecap: "round", strokeLinejoin: "round" }) }) }, "check")), isError && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(ArrowPathIcon, { className: cn("size-3.5", statusIconColor), strokeWidth: 2.5 }) }, "retry"))] }) })] }));
84
+ : undefined, children: [jsxs("svg", { viewBox: `0 0 ${VIEWBOX} ${VIEWBOX}`, className: "w-full h-full -rotate-90", children: [jsx("circle", { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: trackColor, strokeWidth: strokeWidth }), jsx(motion.circle, { cx: CENTER, cy: CENTER, r: radius, fill: "none", stroke: progressColor, strokeWidth: strokeWidth, strokeLinecap: "round", strokeDasharray: circumference, initial: { strokeDashoffset: circumference }, animate: { strokeDashoffset: isComplete ? 0 : offset }, transition: shouldReduceMotion ? { duration: 0 } : PROGRESS_SPRING })] }), jsx("div", { className: "absolute inset-0 flex items-center justify-center", children: jsxs(AnimatePresence, { mode: "wait", initial: false, children: [isUploading && !isHovered && (jsx(motion.span, { className: centerTextStyle, ...(shouldReduceMotion ? {} : CROSSFADE), children: progress }, "percent")), isUploading && isHovered && onRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx(XMarkIcon, { className: "size-4 text-[var(--color-text-muted)]", strokeWidth: 2.5 }) }, "close")), isComplete && !showRemove && (jsx(motion.span, { ...(shouldReduceMotion ? {} : CROSSFADE), children: jsx("svg", { viewBox: "0 0 24 24", fill: "none", className: cn("size-4", statusIconColor), children: jsx("path", { d: "M5 13l4.5 4.5L19 7", stroke: "currentColor", strokeWidth: 3.5, strokeLinecap: "round", strokeLinejoin: "round" }) }) }, "check"))] }) })] }));
74
85
  // Determine what to render: radial indicator or remove button
75
86
  const showRemoveButton = isComplete && showRemove && onRemove;
76
87
  const triggerElement = showRemoveButton ? removeButton : radialElement;
77
- // No confirm popover needed — return the element directly
88
+ // No confirm popover needed — return the element directly.
78
89
  if (!confirmRemove || !onRemove)
79
90
  return triggerElement;
80
- return (jsxs(Popover, { isOpen: confirmOpen, onOpenChange: (open) => {
81
- setConfirmOpen(open);
82
- if (!open)
83
- setIsHovered(false);
84
- }, placement: "bottom-end", offset: isComplete ? 2 : 6, triggerType: "click", children: [jsx(Popover.Trigger, { children: triggerElement }), jsxs(Popover.Body, { portal: false, className: "flex items-center p-0.5 border-[0.5px] rounded-xl gap-0.5", children: [jsx("span", { className: "text-base font-medium text-[var(--color-text-secondary)] px-3", children: isComplete ? "Remove file?" : "Cancel upload?" }), jsx(Button, { size: "sm", color: "danger", variant: "filled", onClick: handleConfirm, children: "Yes" }), jsx(Button, { size: "sm", variant: "soft", color: "neutral", onClick: () => setConfirmOpen(false), children: "No" })] })] }));
91
+ return confirmPopover(triggerElement, isComplete ? "Remove file?" : "Cancel upload?", isComplete ? 2 : 6);
85
92
  };
86
93
  // --- Main Component ---
87
94
  const FileUploadProgress = React__default.forwardRef(({ items, onRemove, onRetry, showFileSize = true, confirmRemove = true, completionDelay = 1500, className, theme: themeOverrides, ...rest }, ref) => {
@@ -103,7 +110,7 @@ const FileUploadProgress = React__default.forwardRef(({ items, onRemove, onRetry
103
110
  const clampedProgress = Math.min(100, Math.max(0, item.progress));
104
111
  const ext = getFileExtension(item.file.name);
105
112
  const hasFileTypeIcon = ext !== null && isKnownFileType(ext);
106
- return (jsxs("div", { className: (_a = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.itemStyle) !== null && _a !== void 0 ? _a : t.itemStyle, children: [hasFileTypeIcon ? (jsx("span", { className: "shrink-0", children: jsx(Icon, { icon: ext, size: "lg" }) })) : (jsx("span", { className: cn((_b = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconContainerStyle) !== null && _b !== void 0 ? _b : t.iconContainerStyle, t.iconSize), children: jsx(DocumentIcon, { className: (_c = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconStyle) !== null && _c !== void 0 ? _c : t.iconStyle }) })), jsxs("div", { className: (_d = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileInfoStyle) !== null && _d !== void 0 ? _d : t.fileInfoStyle, children: [jsx("p", { className: (_e = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileNameStyle) !== null && _e !== void 0 ? _e : t.fileNameStyle, children: item.file.name }), showFileSize && (jsx("p", { className: (_f = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileSizeStyle) !== null && _f !== void 0 ? _f : t.fileSizeStyle, children: formatFileSize(item.file.size) })), item.status === "error" && item.error && (jsx("p", { className: (_g = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.errorTextStyle) !== null && _g !== void 0 ? _g : t.errorTextStyle, children: item.error }))] }), jsx(RadialProgress, { progress: clampedProgress, status: item.status, strokeWidth: t.radialStroke, trackColor: (_h = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialTrackColor) !== null && _h !== void 0 ? _h : t.radialTrackColor, progressColor: radialProgressColors[item.status], centerTextStyle: (_j = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialCenterTextStyle) !== null && _j !== void 0 ? _j : t.radialCenterTextStyle, statusIconColor: statusIconColors[item.status], sizeClass: t.radialSize, shouldReduceMotion: shouldReduceMotion, confirmRemove: confirmRemove, completionDelay: completionDelay, onRemove: onRemove ? () => onRemove(item.id) : undefined, onRetry: onRetry ? () => onRetry(item.id) : undefined })] }, item.id));
113
+ return (jsxs("div", { className: (_a = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.itemStyle) !== null && _a !== void 0 ? _a : t.itemStyle, children: [hasFileTypeIcon ? (jsx("span", { className: "shrink-0", children: jsx(Icon, { icon: ext, size: "lg" }) })) : (jsx("span", { className: cn((_b = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconContainerStyle) !== null && _b !== void 0 ? _b : t.iconContainerStyle, t.iconSize), children: jsx(DocumentIcon, { className: (_c = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.iconStyle) !== null && _c !== void 0 ? _c : t.iconStyle }) })), jsxs("div", { className: (_d = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileInfoStyle) !== null && _d !== void 0 ? _d : t.fileInfoStyle, children: [jsx("p", { className: (_e = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileNameStyle) !== null && _e !== void 0 ? _e : t.fileNameStyle, children: item.file.name }), item.status === "error" && item.error ? (jsx("p", { className: (_f = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.errorTextStyle) !== null && _f !== void 0 ? _f : t.errorTextStyle, children: item.error })) : (showFileSize && (jsx("p", { className: (_g = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.fileSizeStyle) !== null && _g !== void 0 ? _g : t.fileSizeStyle, children: formatFileSize(item.file.size) })))] }), jsx(RadialProgress, { progress: clampedProgress, status: item.status, strokeWidth: t.radialStroke, trackColor: (_h = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialTrackColor) !== null && _h !== void 0 ? _h : t.radialTrackColor, progressColor: radialProgressColors[item.status], centerTextStyle: (_j = themeOverrides === null || themeOverrides === void 0 ? void 0 : themeOverrides.radialCenterTextStyle) !== null && _j !== void 0 ? _j : t.radialCenterTextStyle, statusIconColor: statusIconColors[item.status], sizeClass: t.radialSize, shouldReduceMotion: shouldReduceMotion, confirmRemove: confirmRemove, completionDelay: completionDelay, onRemove: onRemove ? () => onRemove(item.id) : undefined, onRetry: onRetry ? () => onRetry(item.id) : undefined })] }, item.id));
107
114
  }) }));
108
115
  });
109
116
  FileUploadProgress.displayName = "FileUploadProgress";
@@ -6,13 +6,13 @@ const fileUploadProgressTheme = {
6
6
  fileInfoStyle: "flex-1 min-w-0",
7
7
  fileNameStyle: "text-sm font-medium text-[var(--color-text-primary)] truncate",
8
8
  fileSizeStyle: "text-xs text-[var(--color-text-muted)]",
9
- radialTrackColor: "var(--color-background-tertiary)",
9
+ radialTrackColor: "var(--color-surface-sunken)",
10
10
  radialProgressColors: {
11
11
  uploading: "var(--color-primary)",
12
12
  complete: "var(--color-success)",
13
13
  error: "var(--color-danger)",
14
14
  },
15
- radialCenterTextStyle: "text-[10px] font-semibold tabular-nums text-[var(--color-text-secondary)]",
15
+ radialCenterTextStyle: "text-xs tracking-tight font-semibold tabular-nums text-[var(--color-text-secondary)]",
16
16
  statusIconColors: {
17
17
  uploading: "",
18
18
  complete: "text-[var(--color-success)]",
@@ -8,17 +8,15 @@ const inputTheme = {
8
8
  // Base container styles
9
9
  wrapperStyle: formsBaseTheme.wrapperStyle,
10
10
  // Input group styles - no focus-within (focus is managed via JS for contentStart/contentEnd compatibility)
11
- inputGroupStyle: "relative flex rounded-[var(--form-radius)] outline outline-1 outline-[var(--color-border)] " +
11
+ inputGroupStyle: "relative flex rounded-[var(--form-radius)] shadow-[inset_0_0_0_1px_var(--color-border)] " +
12
12
  "bg-white transition-all " +
13
- "dark:bg-[var(--color-neutral-900)] dark:outline-[var(--color-neutral-700)]",
13
+ "dark:shadow-[inset_0_0_0_1px_var(--color-neutral-700)] dark:bg-[var(--color-neutral-900)]",
14
14
  // JS-driven focus ring (applied when isFocused is true)
15
- inputGroupFocusStyle: "outline-2 outline-[var(--color-primary-600)] -outline-offset-1 " +
16
- "ring-4 ring-[var(--color-primary)]/10 " +
17
- "dark:outline-[var(--color-primary-500)] dark:ring-[var(--color-primary-500)]/20",
15
+ inputGroupFocusStyle: "shadow-[inset_0_0_0_2px_var(--color-primary-600)] ring-4 ring-[var(--color-primary)]/10 " +
16
+ "dark:shadow-[inset_0_0_0_2px_var(--color-primary-500)] dark:ring-[var(--color-primary-500)]/20",
18
17
  // JS-driven focus ring for invalid state
19
- inputGroupFocusInvalidStyle: "outline-2 outline-[var(--color-danger)] -outline-offset-1 " +
20
- "ring-4 ring-[var(--color-danger)]/10 " +
21
- "dark:outline-[var(--color-danger-500)] dark:ring-[var(--color-danger-500)]/20",
18
+ inputGroupFocusInvalidStyle: "shadow-[inset_0_0_0_2px_var(--color-danger)] ring-4 ring-[var(--color-danger)]/10 " +
19
+ "dark:shadow-[inset_0_0_0_2px_var(--color-danger-500)] dark:ring-[var(--color-danger-500)]/20",
22
20
  // Base input styles - extends common form control with design tokens
23
21
  baseStyle: `${formsBaseTheme.controlBaseStyle} py-2 px-3`,
24
22
  // Size variants - composed from atomic tokens
@@ -31,8 +29,8 @@ const inputTheme = {
31
29
  states: {
32
30
  default: formsBaseTheme.states.default,
33
31
  disabled: formsBaseTheme.states.disabled,
34
- invalid: "outline-[var(--color-danger)] bg-[var(--color-danger-50)] " +
35
- "dark:bg-[var(--color-danger-950)]/30 dark:outline-[var(--color-danger-500)]",
32
+ invalid: "shadow-[inset_0_0_0_1px_var(--color-danger)] bg-[var(--color-danger-50)] " +
33
+ "dark:bg-[var(--color-danger-950)]/30 dark:shadow-[inset_0_0_0_1px_var(--color-danger-500)]",
36
34
  },
37
35
  // Helper text styles with state handling
38
36
  helperText: formsBaseTheme.helperText,
@@ -67,7 +65,7 @@ const inputTheme = {
67
65
  // Number input controls
68
66
  numberButtonsContainerStyle: "absolute inset-y-0 right-0 flex flex-row items-center pr-2 z-10 gap-1",
69
67
  numberButtonStyle: "bg-[var(--color-background-secondary)] flex items-center justify-center " +
70
- "text-[var(--color-text-muted)] hover:bg-[var(--color-background-tertiary)] " +
68
+ "text-[var(--color-text-muted)] hover:bg-[var(--color-surface-hover)] " +
71
69
  "hover:text-[var(--color-text-primary)] cursor-pointer size-6 rounded-sm transition-colors " +
72
70
  "dark:bg-[var(--color-neutral-800)] dark:text-[var(--color-neutral-500)] " +
73
71
  "dark:hover:bg-[var(--color-neutral-700)] dark:hover:text-[var(--color-neutral-200)]",
@@ -10,9 +10,9 @@ const mentionTheme = {
10
10
  // Input group container with outline and focus ring
11
11
  inputGroupStyle: formsBaseTheme.inputGroupBaseStyle,
12
12
  // JS-driven focus ring (applied when editable div is focused)
13
- inputGroupFocusStyle: "outline-2 outline-[var(--color-primary-600)] -outline-offset-1 " +
13
+ inputGroupFocusStyle: "shadow-[inset_0_0_0_2px_var(--color-primary-600)] " +
14
14
  "ring-4 ring-[var(--color-primary)]/10 " +
15
- "dark:outline-[var(--color-primary-500)] dark:ring-[var(--color-primary-500)]/20",
15
+ "dark:shadow-[inset_0_0_0_2px_var(--color-primary-500)] dark:ring-[var(--color-primary-500)]/20",
16
16
  // Base editable div styles
17
17
  editableStyle: `${formsBaseTheme.controlBaseStyle} whitespace-pre-wrap break-words overflow-y-auto cursor-text`,
18
18
  // Size variants
@@ -35,7 +35,7 @@ const mentionTheme = {
35
35
  "dark:text-[var(--color-primary-400)] dark:bg-[var(--color-primary-400)]/10",
36
36
  // Avatar image
37
37
  suggestionAvatarStyle: "size-7 rounded-full object-cover shrink-0 " +
38
- "bg-[var(--color-background-tertiary)] dark:bg-[var(--color-neutral-700)]",
38
+ "bg-[var(--color-surface-sunken)] dark:bg-[var(--color-neutral-700)]",
39
39
  // Avatar fallback (initials circle)
40
40
  suggestionAvatarFallbackStyle: "size-7 rounded-full shrink-0 flex items-center justify-center text-xs font-medium " +
41
41
  "bg-[var(--color-primary-100)] text-[var(--color-primary-700)] " +
@@ -9,7 +9,7 @@ const radioTheme = {
9
9
  // Default state - light
10
10
  "border-[var(--color-border)] bg-[var(--color-surface)] " +
11
11
  // Default state - dark
12
- "dark:bg-[var(--color-background-tertiary)] " +
12
+ "dark:bg-[var(--color-surface-raised)] " +
13
13
  // Checked state - light
14
14
  "checked:border-[var(--color-primary)] checked:bg-white " +
15
15
  // Checked state - dark
@@ -1,3 +1,21 @@
1
1
  import React from "react";
2
2
  import { RichTextEditorProps } from "./RichTextEditor.types";
3
+ import type { FontFamilyOption } from "./RichTextEditor.types";
4
+ /**
5
+ * Curated default list of font families shipped with the editor.
6
+ * The `Default` entry clears the inline font-family. The rest are popular
7
+ * Google Fonts chosen for broad weight coverage. Each stack ends in a sensible
8
+ * fallback so text stays readable while the font is loading.
9
+ */
10
+ export declare const DEFAULT_FONT_FAMILY_OPTIONS: FontFamilyOption[];
11
+ /**
12
+ * Lazily injects a Google Fonts `<link rel="stylesheet">` for the given family.
13
+ * Idempotent: each family is requested at most once per page lifetime.
14
+ * SSR-safe (no-ops when `document` is undefined).
15
+ *
16
+ * @example
17
+ * import { loadGoogleFont } from "@flikk/ui";
18
+ * loadGoogleFont("Inter");
19
+ */
20
+ export declare const loadGoogleFont: (family: string, weights?: number[]) => void;
3
21
  export declare const RichTextEditor: React.ForwardRefExoticComponent<RichTextEditorProps & React.RefAttributes<HTMLDivElement>>;