jvetrau-ds 0.2.47 → 0.2.49

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 (93) hide show
  1. package/components/course-outline/course-outline.cjs +54 -41
  2. package/components/course-outline/course-outline.cjs.map +1 -1
  3. package/components/course-outline/course-outline.css +56 -3
  4. package/components/course-outline/course-outline.d.ts +4 -0
  5. package/components/course-outline/course-outline.js +52 -42
  6. package/components/course-outline/course-outline.js.map +1 -1
  7. package/components/course-outline/index.cjs +10 -1
  8. package/components/course-outline/index.d.ts +2 -2
  9. package/components/course-outline/index.js +1 -1
  10. package/components/dropdown/dropdown.cjs +34 -5
  11. package/components/dropdown/dropdown.cjs.map +1 -1
  12. package/components/dropdown/dropdown.js +34 -5
  13. package/components/dropdown/dropdown.js.map +1 -1
  14. package/components/index.cjs +4 -0
  15. package/components/index.d.ts +3 -3
  16. package/components/index.js +1 -1
  17. package/components/markdown/index.d.ts +1 -1
  18. package/components/markdown/markdown.cjs +13 -2
  19. package/components/markdown/markdown.cjs.map +1 -1
  20. package/components/markdown/markdown.d.ts +2 -0
  21. package/components/markdown/markdown.js +13 -2
  22. package/components/markdown/markdown.js.map +1 -1
  23. package/index.cjs +4 -0
  24. package/index.d.ts +3 -3
  25. package/index.js +1 -1
  26. package/layouts/base/base.css +1 -1
  27. package/package.json +1 -1
  28. package/styles.css +57 -4
  29. package/themes/base/desktop.css +1 -1
  30. package/themes/base/desktop.md +1 -1
  31. package/themes/base/desktop.scoped.css +1 -1
  32. package/themes/base/diagram.css +1 -1
  33. package/themes/base/diagram.md +1 -1
  34. package/themes/base/diagram.scoped.css +1 -1
  35. package/themes/base/mobile.css +1 -1
  36. package/themes/base/mobile.md +1 -1
  37. package/themes/base/mobile.scoped.css +1 -1
  38. package/themes/base/responsive.css +2 -2
  39. package/themes/brandcopilot/desktop.css +1 -1
  40. package/themes/brandcopilot/desktop.md +1 -1
  41. package/themes/brandcopilot/desktop.scoped.css +1 -1
  42. package/themes/brandcopilot/diagram.css +1 -1
  43. package/themes/brandcopilot/diagram.md +1 -1
  44. package/themes/brandcopilot/diagram.scoped.css +1 -1
  45. package/themes/brandcopilot/mobile.css +1 -1
  46. package/themes/brandcopilot/mobile.md +1 -1
  47. package/themes/brandcopilot/mobile.scoped.css +1 -1
  48. package/themes/brandcopilot/responsive.css +2 -2
  49. package/themes/dmpatterns/desktop.css +1 -1
  50. package/themes/dmpatterns/desktop.md +1 -1
  51. package/themes/dmpatterns/desktop.scoped.css +1 -1
  52. package/themes/dmpatterns/diagram.css +1 -1
  53. package/themes/dmpatterns/diagram.md +1 -1
  54. package/themes/dmpatterns/diagram.scoped.css +1 -1
  55. package/themes/dmpatterns/mobile.css +1 -1
  56. package/themes/dmpatterns/mobile.md +1 -1
  57. package/themes/dmpatterns/mobile.scoped.css +1 -1
  58. package/themes/dmpatterns/responsive.css +2 -2
  59. package/themes/pdigest/desktop.css +1 -1
  60. package/themes/pdigest/desktop.md +1 -1
  61. package/themes/pdigest/desktop.scoped.css +1 -1
  62. package/themes/pdigest/diagram.css +1 -1
  63. package/themes/pdigest/diagram.md +1 -1
  64. package/themes/pdigest/diagram.scoped.css +1 -1
  65. package/themes/pdigest/mobile.css +1 -1
  66. package/themes/pdigest/mobile.md +1 -1
  67. package/themes/pdigest/mobile.scoped.css +1 -1
  68. package/themes/pdigest/responsive.css +2 -2
  69. package/themes/retrack/desktop.css +1 -1
  70. package/themes/retrack/desktop.md +1 -1
  71. package/themes/retrack/desktop.scoped.css +1 -1
  72. package/themes/retrack/diagram.css +1 -1
  73. package/themes/retrack/diagram.md +1 -1
  74. package/themes/retrack/diagram.scoped.css +1 -1
  75. package/themes/retrack/mobile.css +1 -1
  76. package/themes/retrack/mobile.md +1 -1
  77. package/themes/retrack/mobile.scoped.css +1 -1
  78. package/themes/retrack/responsive.css +2 -2
  79. package/tokens/themes/base/dist/desktop.json +1 -1
  80. package/tokens/themes/base/dist/diagram.json +1 -1
  81. package/tokens/themes/base/dist/mobile.json +1 -1
  82. package/tokens/themes/brandcopilot/dist/desktop.json +1 -1
  83. package/tokens/themes/brandcopilot/dist/diagram.json +1 -1
  84. package/tokens/themes/brandcopilot/dist/mobile.json +1 -1
  85. package/tokens/themes/dmpatterns/dist/desktop.json +1 -1
  86. package/tokens/themes/dmpatterns/dist/diagram.json +1 -1
  87. package/tokens/themes/dmpatterns/dist/mobile.json +1 -1
  88. package/tokens/themes/pdigest/dist/desktop.json +1 -1
  89. package/tokens/themes/pdigest/dist/diagram.json +1 -1
  90. package/tokens/themes/pdigest/dist/mobile.json +1 -1
  91. package/tokens/themes/retrack/dist/desktop.json +1 -1
  92. package/tokens/themes/retrack/dist/diagram.json +1 -1
  93. package/tokens/themes/retrack/dist/mobile.json +1 -1
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
3
5
  var jsxRuntime = require('react/jsx-runtime');
4
6
  var React = require('react');
5
7
  require('./course-outline.css');
@@ -29,6 +31,41 @@ function getItemTitle(item) {
29
31
  }
30
32
  return hasContent(item.link) ? item.link : item.title;
31
33
  }
34
+ function getItemClasses(item) {
35
+ return classnames.classnames(
36
+ "course-outline__item",
37
+ "",
38
+ {
39
+ "course-outline__item--active": Boolean(
40
+ item.active
41
+ ),
42
+ "course-outline__item--disabled": Boolean(
43
+ item.disabled
44
+ )
45
+ }
46
+ );
47
+ }
48
+ const CourseOutlineItem = ({ item }) => {
49
+ const hasMeta = hasContent(item.meta);
50
+ const hasStatus = hasContent(item.status);
51
+ const hasAction = hasContent(item.action);
52
+ const hasFooter = hasStatus || hasAction;
53
+ return /* @__PURE__ */ jsxRuntime.jsxs(
54
+ "article",
55
+ {
56
+ className: "course-outline__item-body",
57
+ "aria-disabled": item.disabled ? "true" : void 0,
58
+ children: [
59
+ /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__title", children: getItemTitle(item) }),
60
+ hasMeta && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__meta", children: item.meta }),
61
+ hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "course-outline__footer", children: [
62
+ hasStatus && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__status", children: item.status }),
63
+ hasAction && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__action", children: item.action })
64
+ ] })
65
+ ]
66
+ }
67
+ );
68
+ };
32
69
  const GroupTitle = ({
33
70
  level,
34
71
  children
@@ -139,46 +176,21 @@ const CourseOutline = ({
139
176
  className: "course-outline__items",
140
177
  id: groupContentId,
141
178
  hidden: isCollapsed,
142
- children: group.items.map((item) => {
143
- const hasMeta = hasContent(item.meta);
144
- const hasStatus = hasContent(
145
- item.status
146
- );
147
- const hasAction = hasContent(
148
- item.action
149
- );
150
- const hasFooter = hasStatus || hasAction;
151
- const itemClasses = classnames.classnames(
152
- "course-outline__item",
153
- "",
154
- {
155
- "course-outline__item--active": Boolean(item.active),
156
- "course-outline__item--disabled": Boolean(item.disabled)
157
- }
158
- );
159
- return /* @__PURE__ */ jsxRuntime.jsx(
160
- "li",
161
- {
162
- className: itemClasses,
163
- children: /* @__PURE__ */ jsxRuntime.jsxs(
164
- "article",
165
- {
166
- className: "course-outline__item-body",
167
- "aria-disabled": item.disabled ? "true" : void 0,
168
- children: [
169
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__title", children: getItemTitle(item) }),
170
- hasMeta && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__meta", children: item.meta }),
171
- hasFooter && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "course-outline__footer", children: [
172
- hasStatus && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__status", children: item.status }),
173
- hasAction && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "course-outline__action", children: item.action })
174
- ] })
175
- ]
176
- }
177
- )
178
- },
179
- item.id
180
- );
181
- })
179
+ children: group.items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
180
+ "li",
181
+ {
182
+ className: getItemClasses(
183
+ item
184
+ ),
185
+ children: /* @__PURE__ */ jsxRuntime.jsx(
186
+ CourseOutlineItem,
187
+ {
188
+ item
189
+ }
190
+ )
191
+ },
192
+ item.id
193
+ ))
182
194
  }
183
195
  )
184
196
  ]
@@ -191,6 +203,7 @@ const CourseOutline = ({
191
203
  };
192
204
  var course_outline_default = CourseOutline;
193
205
 
194
- module.exports = course_outline_default;
206
+ exports.CourseOutlineItem = CourseOutlineItem;
207
+ exports.default = course_outline_default;
195
208
  //# sourceMappingURL=course-outline.cjs.map
196
209
  //# sourceMappingURL=course-outline.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/course-outline/course-outline.tsx"],"names":["jsx","React","classnames","jsxs"],"mappings":"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","file":"course-outline.cjs","sourcesContent":["import React from 'react';\n\nimport './course-outline.css';\nimport { classnames } from '../helpers/classnames';\n\nexport type CourseOutlineHeadingLevel =\n | 2\n | 3\n | 4\n | 5\n | 6;\n\nexport interface CourseOutlineItem {\n id: React.Key;\n title: React.ReactNode;\n link?: React.ReactNode;\n meta?: React.ReactNode;\n status?: React.ReactNode;\n action?: React.ReactNode;\n active?: boolean;\n disabled?: boolean;\n}\n\nexport interface CourseOutlineGroup {\n id: React.Key;\n title: React.ReactNode;\n description?: React.ReactNode;\n items: CourseOutlineItem[];\n defaultCollapsed?: boolean;\n}\n\nexport interface CourseOutlineProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children'\n > {\n groups: CourseOutlineGroup[];\n headingLevel?: CourseOutlineHeadingLevel;\n collapsible?: boolean;\n}\n\ntype CollapsedGroups = Map<React.Key, boolean>;\n\nfunction hasContent(\n value: React.ReactNode,\n): value is Exclude<\n React.ReactNode,\n null | undefined\n> {\n return value !== null && value !== undefined;\n}\n\nfunction getInitialCollapsedGroups(\n groups: CourseOutlineGroup[],\n): CollapsedGroups {\n return new Map(\n groups.map((group) => [\n group.id,\n Boolean(group.defaultCollapsed),\n ]),\n );\n}\n\nfunction getGroupCollapsed(\n collapsedGroups: CollapsedGroups,\n group: CourseOutlineGroup,\n) {\n return (\n collapsedGroups.get(group.id) ??\n Boolean(group.defaultCollapsed)\n );\n}\n\nfunction getItemTitle(\n item: CourseOutlineItem,\n): React.ReactNode {\n if (item.active) {\n return item.title;\n }\n\n return hasContent(item.link)\n ? item.link\n : item.title;\n}\n\ninterface GroupTitleProps {\n level?: CourseOutlineHeadingLevel;\n children: React.ReactNode;\n}\n\nconst GroupTitle: React.FC<GroupTitleProps> = ({\n level,\n children,\n}) => {\n if (!level) {\n return (\n <div className=\"course-outline__group-title\">\n {children}\n </div>\n );\n }\n\n switch (level) {\n case 2:\n return (\n <h2 className=\"course-outline__group-title\">\n {children}\n </h2>\n );\n\n case 3:\n return (\n <h3 className=\"course-outline__group-title\">\n {children}\n </h3>\n );\n\n case 4:\n return (\n <h4 className=\"course-outline__group-title\">\n {children}\n </h4>\n );\n\n case 5:\n return (\n <h5 className=\"course-outline__group-title\">\n {children}\n </h5>\n );\n\n default:\n return (\n <h6 className=\"course-outline__group-title\">\n {children}\n </h6>\n );\n }\n};\n\nconst CourseOutline: React.FC<CourseOutlineProps> = ({\n groups,\n headingLevel,\n collapsible = false,\n className = '',\n ...props\n}) => {\n const visibleGroups = React.useMemo(\n () =>\n groups.filter(\n (group) => group.items.length > 0,\n ),\n [groups],\n );\n\n const [collapsedGroups, setCollapsedGroups] =\n React.useState<CollapsedGroups>(() =>\n getInitialCollapsedGroups(visibleGroups),\n );\n\n const componentId = React.useId();\n\n React.useEffect(() => {\n if (!collapsible) {\n return;\n }\n\n setCollapsedGroups((current) => {\n const next = new Map(current);\n let changed = false;\n\n for (const group of visibleGroups) {\n if (!next.has(group.id)) {\n next.set(\n group.id,\n Boolean(group.defaultCollapsed),\n );\n\n changed = true;\n }\n }\n\n return changed ? next : current;\n });\n }, [collapsible, visibleGroups]);\n\n if (visibleGroups.length === 0) {\n return null;\n }\n\n const classes = classnames(\n 'course-outline',\n className,\n {\n 'course-outline--collapsible': collapsible,\n },\n );\n\n const toggleGroup = (\n group: CourseOutlineGroup,\n ) => {\n setCollapsedGroups((current) => {\n const next = new Map(current);\n\n next.set(\n group.id,\n !getGroupCollapsed(current, group),\n );\n\n return next;\n });\n };\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ol className=\"course-outline__groups\">\n {visibleGroups.map((group, groupIndex) => {\n const isCollapsed =\n collapsible &&\n getGroupCollapsed(\n collapsedGroups,\n group,\n );\n\n const groupContentId =\n `${componentId}-group-${groupIndex}`;\n\n return (\n <li\n key={group.id}\n className=\"course-outline__group\"\n >\n <header className=\"course-outline__group-header\">\n <GroupTitle level={headingLevel}>\n {collapsible ? (\n <button\n className=\"course-outline__group-toggle\"\n type=\"button\"\n aria-expanded={!isCollapsed}\n aria-controls={groupContentId}\n onClick={() => toggleGroup(group)}\n >\n {group.title}\n </button>\n ) : (\n group.title\n )}\n </GroupTitle>\n </header>\n\n {hasContent(group.description) && (\n <div className=\"course-outline__group-description\">\n {group.description}\n </div>\n )}\n\n <ol\n className=\"course-outline__items\"\n id={groupContentId}\n hidden={isCollapsed}\n >\n {group.items.map((item) => {\n const hasMeta = hasContent(item.meta);\n const hasStatus = hasContent(\n item.status,\n );\n const hasAction = hasContent(\n item.action,\n );\n\n const hasFooter =\n hasStatus || hasAction;\n\n const itemClasses = classnames(\n 'course-outline__item',\n '',\n {\n 'course-outline__item--active':\n Boolean(item.active),\n\n 'course-outline__item--disabled':\n Boolean(item.disabled),\n },\n );\n\n return (\n <li\n key={item.id}\n className={itemClasses}\n >\n <article\n className=\"course-outline__item-body\"\n aria-disabled={\n item.disabled\n ? 'true'\n : undefined\n }\n >\n <div className=\"course-outline__title\">\n {getItemTitle(item)}\n </div>\n\n {hasMeta && (\n <div className=\"course-outline__meta\">\n {item.meta}\n </div>\n )}\n\n {hasFooter && (\n <div className=\"course-outline__footer\">\n {hasStatus && (\n <div className=\"course-outline__status\">\n {item.status}\n </div>\n )}\n\n {hasAction && (\n <div className=\"course-outline__action\">\n {item.action}\n </div>\n )}\n </div>\n )}\n </article>\n </li>\n );\n })}\n </ol>\n </li>\n );\n })}\n </ol>\n </div>\n );\n};\n\nexport default CourseOutline;\n"]}
1
+ {"version":3,"sources":["../../../src/components/course-outline/course-outline.tsx"],"names":["classnames","jsxs","jsx","React"],"mappings":"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","file":"course-outline.cjs","sourcesContent":["import React from 'react';\n\nimport './course-outline.css';\nimport { classnames } from '../helpers/classnames';\n\nexport type CourseOutlineHeadingLevel =\n | 2\n | 3\n | 4\n | 5\n | 6;\n\nexport interface CourseOutlineItem {\n id: React.Key;\n title: React.ReactNode;\n link?: React.ReactNode;\n meta?: React.ReactNode;\n status?: React.ReactNode;\n action?: React.ReactNode;\n active?: boolean;\n disabled?: boolean;\n}\n\nexport interface CourseOutlineItemProps {\n item: CourseOutlineItem;\n}\n\nexport interface CourseOutlineGroup {\n id: React.Key;\n title: React.ReactNode;\n description?: React.ReactNode;\n items: CourseOutlineItem[];\n defaultCollapsed?: boolean;\n}\n\nexport interface CourseOutlineProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children'\n > {\n groups: CourseOutlineGroup[];\n headingLevel?: CourseOutlineHeadingLevel;\n collapsible?: boolean;\n}\n\ntype CollapsedGroups = Map<React.Key, boolean>;\n\nfunction hasContent(\n value: React.ReactNode,\n): value is Exclude<\n React.ReactNode,\n null | undefined\n> {\n return value !== null && value !== undefined;\n}\n\nfunction getInitialCollapsedGroups(\n groups: CourseOutlineGroup[],\n): CollapsedGroups {\n return new Map(\n groups.map((group) => [\n group.id,\n Boolean(group.defaultCollapsed),\n ]),\n );\n}\n\nfunction getGroupCollapsed(\n collapsedGroups: CollapsedGroups,\n group: CourseOutlineGroup,\n) {\n return (\n collapsedGroups.get(group.id) ??\n Boolean(group.defaultCollapsed)\n );\n}\n\nfunction getItemTitle(\n item: CourseOutlineItem,\n): React.ReactNode {\n if (item.active) {\n return item.title;\n }\n\n return hasContent(item.link)\n ? item.link\n : item.title;\n}\n\nfunction getItemClasses(\n item: CourseOutlineItem,\n) {\n return classnames(\n 'course-outline__item',\n '',\n {\n 'course-outline__item--active': Boolean(\n item.active,\n ),\n\n 'course-outline__item--disabled': Boolean(\n item.disabled,\n ),\n },\n );\n}\n\nexport const CourseOutlineItem: React.FC<\n CourseOutlineItemProps\n> = ({ item }) => {\n const hasMeta = hasContent(item.meta);\n const hasStatus = hasContent(item.status);\n const hasAction = hasContent(item.action);\n const hasFooter = hasStatus || hasAction;\n\n return (\n <article\n className=\"course-outline__item-body\"\n aria-disabled={\n item.disabled ? 'true' : undefined\n }\n >\n <div className=\"course-outline__title\">\n {getItemTitle(item)}\n </div>\n\n {hasMeta && (\n <div className=\"course-outline__meta\">\n {item.meta}\n </div>\n )}\n\n {hasFooter && (\n <div className=\"course-outline__footer\">\n {hasStatus && (\n <div className=\"course-outline__status\">\n {item.status}\n </div>\n )}\n\n {hasAction && (\n <div className=\"course-outline__action\">\n {item.action}\n </div>\n )}\n </div>\n )}\n </article>\n );\n};\n\ninterface GroupTitleProps {\n level?: CourseOutlineHeadingLevel;\n children: React.ReactNode;\n}\n\nconst GroupTitle: React.FC<GroupTitleProps> = ({\n level,\n children,\n}) => {\n if (!level) {\n return (\n <div className=\"course-outline__group-title\">\n {children}\n </div>\n );\n }\n\n switch (level) {\n case 2:\n return (\n <h2 className=\"course-outline__group-title\">\n {children}\n </h2>\n );\n\n case 3:\n return (\n <h3 className=\"course-outline__group-title\">\n {children}\n </h3>\n );\n\n case 4:\n return (\n <h4 className=\"course-outline__group-title\">\n {children}\n </h4>\n );\n\n case 5:\n return (\n <h5 className=\"course-outline__group-title\">\n {children}\n </h5>\n );\n\n default:\n return (\n <h6 className=\"course-outline__group-title\">\n {children}\n </h6>\n );\n }\n};\n\nconst CourseOutline: React.FC<CourseOutlineProps> = ({\n groups,\n headingLevel,\n collapsible = false,\n className = '',\n ...props\n}) => {\n const visibleGroups = React.useMemo(\n () =>\n groups.filter(\n (group) => group.items.length > 0,\n ),\n [groups],\n );\n\n const [collapsedGroups, setCollapsedGroups] =\n React.useState<CollapsedGroups>(() =>\n getInitialCollapsedGroups(visibleGroups),\n );\n\n const componentId = React.useId();\n\n React.useEffect(() => {\n if (!collapsible) {\n return;\n }\n\n setCollapsedGroups((current) => {\n const next = new Map(current);\n let changed = false;\n\n for (const group of visibleGroups) {\n if (!next.has(group.id)) {\n next.set(\n group.id,\n Boolean(group.defaultCollapsed),\n );\n\n changed = true;\n }\n }\n\n return changed ? next : current;\n });\n }, [collapsible, visibleGroups]);\n\n if (visibleGroups.length === 0) {\n return null;\n }\n\n const classes = classnames(\n 'course-outline',\n className,\n {\n 'course-outline--collapsible': collapsible,\n },\n );\n\n const toggleGroup = (\n group: CourseOutlineGroup,\n ) => {\n setCollapsedGroups((current) => {\n const next = new Map(current);\n\n next.set(\n group.id,\n !getGroupCollapsed(current, group),\n );\n\n return next;\n });\n };\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ol className=\"course-outline__groups\">\n {visibleGroups.map((group, groupIndex) => {\n const isCollapsed =\n collapsible &&\n getGroupCollapsed(\n collapsedGroups,\n group,\n );\n\n const groupContentId =\n `${componentId}-group-${groupIndex}`;\n\n return (\n <li\n key={group.id}\n className=\"course-outline__group\"\n >\n <header className=\"course-outline__group-header\">\n <GroupTitle level={headingLevel}>\n {collapsible ? (\n <button\n className=\"course-outline__group-toggle\"\n type=\"button\"\n aria-expanded={!isCollapsed}\n aria-controls={groupContentId}\n onClick={() => toggleGroup(group)}\n >\n {group.title}\n </button>\n ) : (\n group.title\n )}\n </GroupTitle>\n </header>\n\n {hasContent(group.description) && (\n <div className=\"course-outline__group-description\">\n {group.description}\n </div>\n )}\n\n <ol\n className=\"course-outline__items\"\n id={groupContentId}\n hidden={isCollapsed}\n >\n {group.items.map((item) => (\n <li\n key={item.id}\n className={getItemClasses(\n item,\n )}\n >\n <CourseOutlineItem\n item={item}\n />\n </li>\n ))}\n </ol>\n </li>\n );\n })}\n </ol>\n </div>\n );\n};\n\nexport default CourseOutline;\n"]}
@@ -77,6 +77,23 @@
77
77
  .layout-sidebar__side .course-outline {
78
78
  /* color */
79
79
 
80
+ /* typography */
81
+
82
+ /* size */
83
+ --course-outline-group-gap:
84
+ var(--margin-item);
85
+
86
+ /* border */
87
+
88
+ /* depth */
89
+
90
+ /* motion */
91
+ }
92
+
93
+ .layout-sidebar__side
94
+ .course-outline__item-body {
95
+ /* color */
96
+
80
97
  /* typography */
81
98
  --course-outline-item-title-font-family:
82
99
  var(--font-body-family);
@@ -90,8 +107,6 @@
90
107
  var(--font-body-letter-spacing);
91
108
 
92
109
  /* size */
93
- --course-outline-group-gap:
94
- var(--margin-item);
95
110
 
96
111
  /* border */
97
112
 
@@ -102,7 +117,7 @@
102
117
 
103
118
  .layout-sidebar__side
104
119
  .course-outline__action,
105
- .layout-sidebar__side
120
+ .layout-sidebar__side
106
121
  .course-outline__meta {
107
122
  /* color */
108
123
 
@@ -409,10 +424,48 @@ h4.course-outline__group-title {
409
424
 
410
425
  .course-outline__item-body {
411
426
  /* color */
427
+ --course-outline-meta-color: var(--color-text-note);
412
428
 
413
429
  /* typography */
430
+ --course-outline-item-title-font-family:
431
+ var(--font-lead-family);
432
+ --course-outline-item-title-font-size:
433
+ var(--font-lead);
434
+ --course-outline-item-title-font-weight:
435
+ var(--font-lead-weight);
436
+ --course-outline-item-title-line-height:
437
+ var(--font-lead-line);
438
+ --course-outline-item-title-letter-spacing:
439
+ var(--font-lead-letter-spacing);
440
+
441
+ --course-outline-body-font-family:
442
+ var(--font-body-family);
443
+ --course-outline-body-font-size:
444
+ var(--font-body);
445
+ --course-outline-body-font-weight:
446
+ var(--font-body-weight);
447
+ --course-outline-body-line-height:
448
+ var(--font-body-line);
449
+ --course-outline-body-letter-spacing:
450
+ var(--font-body-letter-spacing);
451
+
452
+ --course-outline-note-font-family:
453
+ var(--font-body-family);
454
+ --course-outline-note-font-size:
455
+ var(--font-note);
456
+ --course-outline-note-font-weight:
457
+ var(--font-note-weight);
458
+ --course-outline-note-line-height:
459
+ var(--font-note-line);
460
+ --course-outline-note-letter-spacing:
461
+ var(--font-note-letter-spacing);
414
462
 
415
463
  /* size */
464
+ --course-outline-item-content-gap:
465
+ var(--margin-descriptor);
466
+ --course-outline-details-gap:
467
+ var(--font-body-margin);
468
+
416
469
  display: flex;
417
470
  flex-direction: column;
418
471
  align-items: flex-start;
@@ -11,6 +11,9 @@ export interface CourseOutlineItem {
11
11
  active?: boolean;
12
12
  disabled?: boolean;
13
13
  }
14
+ export interface CourseOutlineItemProps {
15
+ item: CourseOutlineItem;
16
+ }
14
17
  export interface CourseOutlineGroup {
15
18
  id: React.Key;
16
19
  title: React.ReactNode;
@@ -23,5 +26,6 @@ export interface CourseOutlineProps extends Omit<React.HTMLAttributes<HTMLDivEle
23
26
  headingLevel?: CourseOutlineHeadingLevel;
24
27
  collapsible?: boolean;
25
28
  }
29
+ export declare const CourseOutlineItem: React.FC<CourseOutlineItemProps>;
26
30
  declare const CourseOutline: React.FC<CourseOutlineProps>;
27
31
  export default CourseOutline;
@@ -1,4 +1,4 @@
1
- import { jsx, jsxs } from 'react/jsx-runtime';
1
+ import { jsxs, jsx } from 'react/jsx-runtime';
2
2
  import React from 'react';
3
3
  import './course-outline.css';
4
4
  import { classnames } from '../helpers/classnames';
@@ -23,6 +23,41 @@ function getItemTitle(item) {
23
23
  }
24
24
  return hasContent(item.link) ? item.link : item.title;
25
25
  }
26
+ function getItemClasses(item) {
27
+ return classnames(
28
+ "course-outline__item",
29
+ "",
30
+ {
31
+ "course-outline__item--active": Boolean(
32
+ item.active
33
+ ),
34
+ "course-outline__item--disabled": Boolean(
35
+ item.disabled
36
+ )
37
+ }
38
+ );
39
+ }
40
+ const CourseOutlineItem = ({ item }) => {
41
+ const hasMeta = hasContent(item.meta);
42
+ const hasStatus = hasContent(item.status);
43
+ const hasAction = hasContent(item.action);
44
+ const hasFooter = hasStatus || hasAction;
45
+ return /* @__PURE__ */ jsxs(
46
+ "article",
47
+ {
48
+ className: "course-outline__item-body",
49
+ "aria-disabled": item.disabled ? "true" : void 0,
50
+ children: [
51
+ /* @__PURE__ */ jsx("div", { className: "course-outline__title", children: getItemTitle(item) }),
52
+ hasMeta && /* @__PURE__ */ jsx("div", { className: "course-outline__meta", children: item.meta }),
53
+ hasFooter && /* @__PURE__ */ jsxs("div", { className: "course-outline__footer", children: [
54
+ hasStatus && /* @__PURE__ */ jsx("div", { className: "course-outline__status", children: item.status }),
55
+ hasAction && /* @__PURE__ */ jsx("div", { className: "course-outline__action", children: item.action })
56
+ ] })
57
+ ]
58
+ }
59
+ );
60
+ };
26
61
  const GroupTitle = ({
27
62
  level,
28
63
  children
@@ -133,46 +168,21 @@ const CourseOutline = ({
133
168
  className: "course-outline__items",
134
169
  id: groupContentId,
135
170
  hidden: isCollapsed,
136
- children: group.items.map((item) => {
137
- const hasMeta = hasContent(item.meta);
138
- const hasStatus = hasContent(
139
- item.status
140
- );
141
- const hasAction = hasContent(
142
- item.action
143
- );
144
- const hasFooter = hasStatus || hasAction;
145
- const itemClasses = classnames(
146
- "course-outline__item",
147
- "",
148
- {
149
- "course-outline__item--active": Boolean(item.active),
150
- "course-outline__item--disabled": Boolean(item.disabled)
151
- }
152
- );
153
- return /* @__PURE__ */ jsx(
154
- "li",
155
- {
156
- className: itemClasses,
157
- children: /* @__PURE__ */ jsxs(
158
- "article",
159
- {
160
- className: "course-outline__item-body",
161
- "aria-disabled": item.disabled ? "true" : void 0,
162
- children: [
163
- /* @__PURE__ */ jsx("div", { className: "course-outline__title", children: getItemTitle(item) }),
164
- hasMeta && /* @__PURE__ */ jsx("div", { className: "course-outline__meta", children: item.meta }),
165
- hasFooter && /* @__PURE__ */ jsxs("div", { className: "course-outline__footer", children: [
166
- hasStatus && /* @__PURE__ */ jsx("div", { className: "course-outline__status", children: item.status }),
167
- hasAction && /* @__PURE__ */ jsx("div", { className: "course-outline__action", children: item.action })
168
- ] })
169
- ]
170
- }
171
- )
172
- },
173
- item.id
174
- );
175
- })
171
+ children: group.items.map((item) => /* @__PURE__ */ jsx(
172
+ "li",
173
+ {
174
+ className: getItemClasses(
175
+ item
176
+ ),
177
+ children: /* @__PURE__ */ jsx(
178
+ CourseOutlineItem,
179
+ {
180
+ item
181
+ }
182
+ )
183
+ },
184
+ item.id
185
+ ))
176
186
  }
177
187
  )
178
188
  ]
@@ -185,6 +195,6 @@ const CourseOutline = ({
185
195
  };
186
196
  var course_outline_default = CourseOutline;
187
197
 
188
- export { course_outline_default as default };
198
+ export { CourseOutlineItem, course_outline_default as default };
189
199
  //# sourceMappingURL=course-outline.js.map
190
200
  //# sourceMappingURL=course-outline.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../src/components/course-outline/course-outline.tsx"],"names":[],"mappings":"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","file":"course-outline.js","sourcesContent":["import React from 'react';\n\nimport './course-outline.css';\nimport { classnames } from '../helpers/classnames';\n\nexport type CourseOutlineHeadingLevel =\n | 2\n | 3\n | 4\n | 5\n | 6;\n\nexport interface CourseOutlineItem {\n id: React.Key;\n title: React.ReactNode;\n link?: React.ReactNode;\n meta?: React.ReactNode;\n status?: React.ReactNode;\n action?: React.ReactNode;\n active?: boolean;\n disabled?: boolean;\n}\n\nexport interface CourseOutlineGroup {\n id: React.Key;\n title: React.ReactNode;\n description?: React.ReactNode;\n items: CourseOutlineItem[];\n defaultCollapsed?: boolean;\n}\n\nexport interface CourseOutlineProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children'\n > {\n groups: CourseOutlineGroup[];\n headingLevel?: CourseOutlineHeadingLevel;\n collapsible?: boolean;\n}\n\ntype CollapsedGroups = Map<React.Key, boolean>;\n\nfunction hasContent(\n value: React.ReactNode,\n): value is Exclude<\n React.ReactNode,\n null | undefined\n> {\n return value !== null && value !== undefined;\n}\n\nfunction getInitialCollapsedGroups(\n groups: CourseOutlineGroup[],\n): CollapsedGroups {\n return new Map(\n groups.map((group) => [\n group.id,\n Boolean(group.defaultCollapsed),\n ]),\n );\n}\n\nfunction getGroupCollapsed(\n collapsedGroups: CollapsedGroups,\n group: CourseOutlineGroup,\n) {\n return (\n collapsedGroups.get(group.id) ??\n Boolean(group.defaultCollapsed)\n );\n}\n\nfunction getItemTitle(\n item: CourseOutlineItem,\n): React.ReactNode {\n if (item.active) {\n return item.title;\n }\n\n return hasContent(item.link)\n ? item.link\n : item.title;\n}\n\ninterface GroupTitleProps {\n level?: CourseOutlineHeadingLevel;\n children: React.ReactNode;\n}\n\nconst GroupTitle: React.FC<GroupTitleProps> = ({\n level,\n children,\n}) => {\n if (!level) {\n return (\n <div className=\"course-outline__group-title\">\n {children}\n </div>\n );\n }\n\n switch (level) {\n case 2:\n return (\n <h2 className=\"course-outline__group-title\">\n {children}\n </h2>\n );\n\n case 3:\n return (\n <h3 className=\"course-outline__group-title\">\n {children}\n </h3>\n );\n\n case 4:\n return (\n <h4 className=\"course-outline__group-title\">\n {children}\n </h4>\n );\n\n case 5:\n return (\n <h5 className=\"course-outline__group-title\">\n {children}\n </h5>\n );\n\n default:\n return (\n <h6 className=\"course-outline__group-title\">\n {children}\n </h6>\n );\n }\n};\n\nconst CourseOutline: React.FC<CourseOutlineProps> = ({\n groups,\n headingLevel,\n collapsible = false,\n className = '',\n ...props\n}) => {\n const visibleGroups = React.useMemo(\n () =>\n groups.filter(\n (group) => group.items.length > 0,\n ),\n [groups],\n );\n\n const [collapsedGroups, setCollapsedGroups] =\n React.useState<CollapsedGroups>(() =>\n getInitialCollapsedGroups(visibleGroups),\n );\n\n const componentId = React.useId();\n\n React.useEffect(() => {\n if (!collapsible) {\n return;\n }\n\n setCollapsedGroups((current) => {\n const next = new Map(current);\n let changed = false;\n\n for (const group of visibleGroups) {\n if (!next.has(group.id)) {\n next.set(\n group.id,\n Boolean(group.defaultCollapsed),\n );\n\n changed = true;\n }\n }\n\n return changed ? next : current;\n });\n }, [collapsible, visibleGroups]);\n\n if (visibleGroups.length === 0) {\n return null;\n }\n\n const classes = classnames(\n 'course-outline',\n className,\n {\n 'course-outline--collapsible': collapsible,\n },\n );\n\n const toggleGroup = (\n group: CourseOutlineGroup,\n ) => {\n setCollapsedGroups((current) => {\n const next = new Map(current);\n\n next.set(\n group.id,\n !getGroupCollapsed(current, group),\n );\n\n return next;\n });\n };\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ol className=\"course-outline__groups\">\n {visibleGroups.map((group, groupIndex) => {\n const isCollapsed =\n collapsible &&\n getGroupCollapsed(\n collapsedGroups,\n group,\n );\n\n const groupContentId =\n `${componentId}-group-${groupIndex}`;\n\n return (\n <li\n key={group.id}\n className=\"course-outline__group\"\n >\n <header className=\"course-outline__group-header\">\n <GroupTitle level={headingLevel}>\n {collapsible ? (\n <button\n className=\"course-outline__group-toggle\"\n type=\"button\"\n aria-expanded={!isCollapsed}\n aria-controls={groupContentId}\n onClick={() => toggleGroup(group)}\n >\n {group.title}\n </button>\n ) : (\n group.title\n )}\n </GroupTitle>\n </header>\n\n {hasContent(group.description) && (\n <div className=\"course-outline__group-description\">\n {group.description}\n </div>\n )}\n\n <ol\n className=\"course-outline__items\"\n id={groupContentId}\n hidden={isCollapsed}\n >\n {group.items.map((item) => {\n const hasMeta = hasContent(item.meta);\n const hasStatus = hasContent(\n item.status,\n );\n const hasAction = hasContent(\n item.action,\n );\n\n const hasFooter =\n hasStatus || hasAction;\n\n const itemClasses = classnames(\n 'course-outline__item',\n '',\n {\n 'course-outline__item--active':\n Boolean(item.active),\n\n 'course-outline__item--disabled':\n Boolean(item.disabled),\n },\n );\n\n return (\n <li\n key={item.id}\n className={itemClasses}\n >\n <article\n className=\"course-outline__item-body\"\n aria-disabled={\n item.disabled\n ? 'true'\n : undefined\n }\n >\n <div className=\"course-outline__title\">\n {getItemTitle(item)}\n </div>\n\n {hasMeta && (\n <div className=\"course-outline__meta\">\n {item.meta}\n </div>\n )}\n\n {hasFooter && (\n <div className=\"course-outline__footer\">\n {hasStatus && (\n <div className=\"course-outline__status\">\n {item.status}\n </div>\n )}\n\n {hasAction && (\n <div className=\"course-outline__action\">\n {item.action}\n </div>\n )}\n </div>\n )}\n </article>\n </li>\n );\n })}\n </ol>\n </li>\n );\n })}\n </ol>\n </div>\n );\n};\n\nexport default CourseOutline;\n"]}
1
+ {"version":3,"sources":["../../../src/components/course-outline/course-outline.tsx"],"names":[],"mappings":"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","file":"course-outline.js","sourcesContent":["import React from 'react';\n\nimport './course-outline.css';\nimport { classnames } from '../helpers/classnames';\n\nexport type CourseOutlineHeadingLevel =\n | 2\n | 3\n | 4\n | 5\n | 6;\n\nexport interface CourseOutlineItem {\n id: React.Key;\n title: React.ReactNode;\n link?: React.ReactNode;\n meta?: React.ReactNode;\n status?: React.ReactNode;\n action?: React.ReactNode;\n active?: boolean;\n disabled?: boolean;\n}\n\nexport interface CourseOutlineItemProps {\n item: CourseOutlineItem;\n}\n\nexport interface CourseOutlineGroup {\n id: React.Key;\n title: React.ReactNode;\n description?: React.ReactNode;\n items: CourseOutlineItem[];\n defaultCollapsed?: boolean;\n}\n\nexport interface CourseOutlineProps\n extends Omit<\n React.HTMLAttributes<HTMLDivElement>,\n 'children'\n > {\n groups: CourseOutlineGroup[];\n headingLevel?: CourseOutlineHeadingLevel;\n collapsible?: boolean;\n}\n\ntype CollapsedGroups = Map<React.Key, boolean>;\n\nfunction hasContent(\n value: React.ReactNode,\n): value is Exclude<\n React.ReactNode,\n null | undefined\n> {\n return value !== null && value !== undefined;\n}\n\nfunction getInitialCollapsedGroups(\n groups: CourseOutlineGroup[],\n): CollapsedGroups {\n return new Map(\n groups.map((group) => [\n group.id,\n Boolean(group.defaultCollapsed),\n ]),\n );\n}\n\nfunction getGroupCollapsed(\n collapsedGroups: CollapsedGroups,\n group: CourseOutlineGroup,\n) {\n return (\n collapsedGroups.get(group.id) ??\n Boolean(group.defaultCollapsed)\n );\n}\n\nfunction getItemTitle(\n item: CourseOutlineItem,\n): React.ReactNode {\n if (item.active) {\n return item.title;\n }\n\n return hasContent(item.link)\n ? item.link\n : item.title;\n}\n\nfunction getItemClasses(\n item: CourseOutlineItem,\n) {\n return classnames(\n 'course-outline__item',\n '',\n {\n 'course-outline__item--active': Boolean(\n item.active,\n ),\n\n 'course-outline__item--disabled': Boolean(\n item.disabled,\n ),\n },\n );\n}\n\nexport const CourseOutlineItem: React.FC<\n CourseOutlineItemProps\n> = ({ item }) => {\n const hasMeta = hasContent(item.meta);\n const hasStatus = hasContent(item.status);\n const hasAction = hasContent(item.action);\n const hasFooter = hasStatus || hasAction;\n\n return (\n <article\n className=\"course-outline__item-body\"\n aria-disabled={\n item.disabled ? 'true' : undefined\n }\n >\n <div className=\"course-outline__title\">\n {getItemTitle(item)}\n </div>\n\n {hasMeta && (\n <div className=\"course-outline__meta\">\n {item.meta}\n </div>\n )}\n\n {hasFooter && (\n <div className=\"course-outline__footer\">\n {hasStatus && (\n <div className=\"course-outline__status\">\n {item.status}\n </div>\n )}\n\n {hasAction && (\n <div className=\"course-outline__action\">\n {item.action}\n </div>\n )}\n </div>\n )}\n </article>\n );\n};\n\ninterface GroupTitleProps {\n level?: CourseOutlineHeadingLevel;\n children: React.ReactNode;\n}\n\nconst GroupTitle: React.FC<GroupTitleProps> = ({\n level,\n children,\n}) => {\n if (!level) {\n return (\n <div className=\"course-outline__group-title\">\n {children}\n </div>\n );\n }\n\n switch (level) {\n case 2:\n return (\n <h2 className=\"course-outline__group-title\">\n {children}\n </h2>\n );\n\n case 3:\n return (\n <h3 className=\"course-outline__group-title\">\n {children}\n </h3>\n );\n\n case 4:\n return (\n <h4 className=\"course-outline__group-title\">\n {children}\n </h4>\n );\n\n case 5:\n return (\n <h5 className=\"course-outline__group-title\">\n {children}\n </h5>\n );\n\n default:\n return (\n <h6 className=\"course-outline__group-title\">\n {children}\n </h6>\n );\n }\n};\n\nconst CourseOutline: React.FC<CourseOutlineProps> = ({\n groups,\n headingLevel,\n collapsible = false,\n className = '',\n ...props\n}) => {\n const visibleGroups = React.useMemo(\n () =>\n groups.filter(\n (group) => group.items.length > 0,\n ),\n [groups],\n );\n\n const [collapsedGroups, setCollapsedGroups] =\n React.useState<CollapsedGroups>(() =>\n getInitialCollapsedGroups(visibleGroups),\n );\n\n const componentId = React.useId();\n\n React.useEffect(() => {\n if (!collapsible) {\n return;\n }\n\n setCollapsedGroups((current) => {\n const next = new Map(current);\n let changed = false;\n\n for (const group of visibleGroups) {\n if (!next.has(group.id)) {\n next.set(\n group.id,\n Boolean(group.defaultCollapsed),\n );\n\n changed = true;\n }\n }\n\n return changed ? next : current;\n });\n }, [collapsible, visibleGroups]);\n\n if (visibleGroups.length === 0) {\n return null;\n }\n\n const classes = classnames(\n 'course-outline',\n className,\n {\n 'course-outline--collapsible': collapsible,\n },\n );\n\n const toggleGroup = (\n group: CourseOutlineGroup,\n ) => {\n setCollapsedGroups((current) => {\n const next = new Map(current);\n\n next.set(\n group.id,\n !getGroupCollapsed(current, group),\n );\n\n return next;\n });\n };\n\n return (\n <div\n className={classes}\n {...props}\n >\n <ol className=\"course-outline__groups\">\n {visibleGroups.map((group, groupIndex) => {\n const isCollapsed =\n collapsible &&\n getGroupCollapsed(\n collapsedGroups,\n group,\n );\n\n const groupContentId =\n `${componentId}-group-${groupIndex}`;\n\n return (\n <li\n key={group.id}\n className=\"course-outline__group\"\n >\n <header className=\"course-outline__group-header\">\n <GroupTitle level={headingLevel}>\n {collapsible ? (\n <button\n className=\"course-outline__group-toggle\"\n type=\"button\"\n aria-expanded={!isCollapsed}\n aria-controls={groupContentId}\n onClick={() => toggleGroup(group)}\n >\n {group.title}\n </button>\n ) : (\n group.title\n )}\n </GroupTitle>\n </header>\n\n {hasContent(group.description) && (\n <div className=\"course-outline__group-description\">\n {group.description}\n </div>\n )}\n\n <ol\n className=\"course-outline__items\"\n id={groupContentId}\n hidden={isCollapsed}\n >\n {group.items.map((item) => (\n <li\n key={item.id}\n className={getItemClasses(\n item,\n )}\n >\n <CourseOutlineItem\n item={item}\n />\n </li>\n ))}\n </ol>\n </li>\n );\n })}\n </ol>\n </div>\n );\n};\n\nexport default CourseOutline;\n"]}
@@ -1,5 +1,7 @@
1
1
  'use strict';
2
2
 
3
+ Object.defineProperty(exports, '__esModule', { value: true });
4
+
3
5
  var courseOutline = require('./course-outline');
4
6
 
5
7
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
@@ -8,6 +10,13 @@ var courseOutline__default = /*#__PURE__*/_interopDefault(courseOutline);
8
10
 
9
11
 
10
12
 
11
- module.exports = courseOutline__default.default;
13
+ Object.defineProperty(exports, "CourseOutlineItem", {
14
+ enumerable: true,
15
+ get: function () { return courseOutline.CourseOutlineItem; }
16
+ });
17
+ Object.defineProperty(exports, "default", {
18
+ enumerable: true,
19
+ get: function () { return courseOutline__default.default; }
20
+ });
12
21
  //# sourceMappingURL=index.cjs.map
13
22
  //# sourceMappingURL=index.cjs.map
@@ -1,2 +1,2 @@
1
- export { default } from './course-outline';
2
- export type { CourseOutlineGroup, CourseOutlineHeadingLevel, CourseOutlineItem, CourseOutlineProps, } from './course-outline';
1
+ export { default, CourseOutlineItem, } from './course-outline';
2
+ export type { CourseOutlineGroup, CourseOutlineHeadingLevel, CourseOutlineItemProps, CourseOutlineProps, } from './course-outline';
@@ -1,3 +1,3 @@
1
- export { default } from './course-outline';
1
+ export { CourseOutlineItem, default } from './course-outline';
2
2
  //# sourceMappingURL=index.js.map
3
3
  //# sourceMappingURL=index.js.map
@@ -5,6 +5,7 @@ var react = require('react');
5
5
  require('./dropdown.css');
6
6
  var classnames = require('../helpers/classnames');
7
7
 
8
+ const HOVER_CLOSE_DELAY_MS = 150;
8
9
  const Dropdown = ({
9
10
  options,
10
11
  value,
@@ -22,6 +23,7 @@ const Dropdown = ({
22
23
  ...props
23
24
  }) => {
24
25
  const dropdownRef = react.useRef(null);
26
+ const hoverCloseTimeoutRef = react.useRef(null);
25
27
  const [isOpen, setIsOpen] = react.useState(false);
26
28
  const [
27
29
  internalValue,
@@ -29,6 +31,26 @@ const Dropdown = ({
29
31
  ] = react.useState(defaultValue);
30
32
  const selectedValue = value ?? internalValue;
31
33
  const isHoverInteraction = interaction === "hover";
34
+ const clearHoverCloseTimeout = () => {
35
+ if (hoverCloseTimeoutRef.current === null) {
36
+ return;
37
+ }
38
+ clearTimeout(
39
+ hoverCloseTimeoutRef.current
40
+ );
41
+ hoverCloseTimeoutRef.current = null;
42
+ };
43
+ const closeDropdown = () => {
44
+ clearHoverCloseTimeout();
45
+ setIsOpen(false);
46
+ };
47
+ const scheduleHoverClose = () => {
48
+ clearHoverCloseTimeout();
49
+ hoverCloseTimeoutRef.current = setTimeout(() => {
50
+ hoverCloseTimeoutRef.current = null;
51
+ setIsOpen(false);
52
+ }, HOVER_CLOSE_DELAY_MS);
53
+ };
32
54
  const classes = classnames.classnames(
33
55
  "dropdown",
34
56
  className,
@@ -72,23 +94,25 @@ const Dropdown = ({
72
94
  setInternalValue(option.value);
73
95
  }
74
96
  onChange?.(option.value);
75
- setIsOpen(false);
97
+ closeDropdown();
76
98
  };
77
99
  const handleMouseEnter = (event) => {
78
100
  onMouseEnter?.(event);
79
101
  if (isHoverInteraction) {
102
+ clearHoverCloseTimeout();
80
103
  setIsOpen(true);
81
104
  }
82
105
  };
83
106
  const handleMouseLeave = (event) => {
84
107
  onMouseLeave?.(event);
85
108
  if (isHoverInteraction) {
86
- setIsOpen(false);
109
+ scheduleHoverClose();
87
110
  }
88
111
  };
89
112
  const handleFocus = (event) => {
90
113
  onFocus?.(event);
91
114
  if (isHoverInteraction) {
115
+ clearHoverCloseTimeout();
92
116
  setIsOpen(true);
93
117
  }
94
118
  };
@@ -103,8 +127,13 @@ const Dropdown = ({
103
127
  )) {
104
128
  return;
105
129
  }
106
- setIsOpen(false);
130
+ closeDropdown();
107
131
  };
132
+ react.useEffect(() => {
133
+ return () => {
134
+ clearHoverCloseTimeout();
135
+ };
136
+ }, []);
108
137
  react.useEffect(() => {
109
138
  if (!isOpen) {
110
139
  return;
@@ -116,11 +145,11 @@ const Dropdown = ({
116
145
  )) {
117
146
  return;
118
147
  }
119
- setIsOpen(false);
148
+ closeDropdown();
120
149
  };
121
150
  const handleDocumentKeyDown = (event) => {
122
151
  if (event.key === "Escape") {
123
- setIsOpen(false);
152
+ closeDropdown();
124
153
  }
125
154
  };
126
155
  document.addEventListener(