@examplary/ui 1.39.0 → 1.39.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -39,7 +39,18 @@ import * as _ReactDom from "react-dom";
39
39
  import * as _jsxRuntime from "react/jsx-runtime";
40
40
  import * as ExamplaryUI from "../../index";
41
41
  var componentCache = new Map();
42
- // Little helper to evaluate the JS code in the context of the module
42
+ /**
43
+ * Little helper to evaluate the JS code in the context of the module.
44
+ *
45
+ * Note for security analysis: this is not a security risk on its own,
46
+ * as the code executed by this (from custom question types created
47
+ * either by Examplary or submitted by users) has been reviewed by
48
+ * Examplary staff, before being made available to accounts other than
49
+ * the creator.
50
+ *
51
+ * However, if the code being evaluated here were to be modified by an attacker
52
+ * after review, but before being loaded by users, then this could be a security risk.
53
+ */
43
54
  var evalInScope = function (js, contextAsScope) {
44
55
  return new Function("\n with (this) { \n ".concat(js, "\n \n if (module.exports.default) {\n module.exports.default._context = this;\n }\n }\n ")).call(contextAsScope);
45
56
  };
@@ -1,4 +1,5 @@
1
1
  import * as React from "react";
2
+ import { LucideProps } from "lucide-react";
2
3
  import { PopoverTrigger } from "./popover";
3
4
  type IconData = {
4
5
  name: string;
@@ -14,8 +15,12 @@ interface IconPickerProps extends Omit<React.ComponentPropsWithoutRef<typeof Pop
14
15
  className?: string;
15
16
  iconsList?: IconData[];
16
17
  }
17
- declare const IconPicker: {
18
+ type DynamicIconProps = {
19
+ name: string;
20
+ } & LucideProps;
21
+ export declare const DynamicIcon: React.MemoExoticComponent<({ name, ...props }: DynamicIconProps) => import("react/jsx-runtime").JSX.Element>;
22
+ export declare const IconPicker: {
18
23
  ({ value, defaultValue, onValueChange, children, chooseIconLabel, searchable, searchPlaceholder, iconsList, className, ...props }: IconPickerProps): import("react/jsx-runtime").JSX.Element;
19
24
  displayName: string;
20
25
  };
21
- export { IconPicker };
26
+ export {};
@@ -60,20 +60,42 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
60
60
  import * as React from "react";
61
61
  import { useState, useMemo, useCallback, useEffect } from "react";
62
62
  import Fuse from "fuse.js";
63
- import { DynamicIcon } from "lucide-react/dynamic";
63
+ import { Icon } from "lucide-react";
64
64
  import { useDebounceValue } from "usehooks-ts";
65
65
  import { Button } from "./button";
66
66
  import { Input } from "./input";
67
67
  import { Popover, PopoverContent, PopoverTrigger } from "./popover";
68
68
  import { Skeleton } from "./skeleton";
69
- var IconRenderer = React.memo(function (_a) {
70
- var name = _a.name;
71
- return _jsx(DynamicIcon, { name: name });
72
- });
73
- IconRenderer.displayName = "IconRenderer";
74
69
  var IconsColumnSkeleton = function () {
75
70
  return (_jsxs("div", { className: "flex flex-col gap-2 w-full", children: [_jsx(Skeleton, { className: "h-4 w-1/2 rounded-md" }), _jsx("div", { className: "grid grid-cols-5 gap-2 w-full", children: Array.from({ length: 40 }).map(function (_, i) { return (_jsx(Skeleton, { className: "h-10 w-10 rounded-md" }, i)); }) })] }));
76
71
  };
72
+ export var DynamicIcon = React.memo(function (_a) {
73
+ var name = _a.name, props = __rest(_a, ["name"]);
74
+ var _b = useState([]), node = _b[0], setNode = _b[1];
75
+ useEffect(function () {
76
+ var isMounted = true;
77
+ var loadIcon = function () { return __awaiter(void 0, void 0, void 0, function () {
78
+ var response;
79
+ return __generator(this, function (_a) {
80
+ switch (_a.label) {
81
+ case 0: return [4 /*yield*/, import("lucide-static/icon-nodes.json")];
82
+ case 1:
83
+ response = _a.sent();
84
+ if (isMounted) {
85
+ setNode(response.default[name]);
86
+ }
87
+ return [2 /*return*/];
88
+ }
89
+ });
90
+ }); };
91
+ loadIcon();
92
+ return function () {
93
+ isMounted = false;
94
+ };
95
+ }, [name]);
96
+ return _jsx(Icon, __assign({}, props, { iconNode: node }));
97
+ });
98
+ DynamicIcon.displayName = "DynamicIcon";
77
99
  var useIconsData = function () {
78
100
  var _a = useState([]), icons = _a[0], setIcons = _a[1];
79
101
  var _b = useState(true), isLoading = _b[0], setIsLoading = _b[1];
@@ -109,7 +131,7 @@ var useIconsData = function () {
109
131
  }, []);
110
132
  return { icons: icons, isLoading: isLoading };
111
133
  };
112
- var IconPicker = function (_a) {
134
+ export var IconPicker = function (_a) {
113
135
  var value = _a.value, defaultValue = _a.defaultValue, onValueChange = _a.onValueChange, children = _a.children, chooseIconLabel = _a.chooseIconLabel, _b = _a.searchable, searchable = _b === void 0 ? true : _b, _c = _a.searchPlaceholder, searchPlaceholder = _c === void 0 ? "Search for an icon..." : _c, iconsList = _a.iconsList, className = _a.className, props = __rest(_a, ["value", "defaultValue", "onValueChange", "children", "chooseIconLabel", "searchable", "searchPlaceholder", "iconsList", "className"]);
114
136
  var _d = useState(defaultValue), selectedIcon = _d[0], setSelectedIcon = _d[1];
115
137
  var _e = useState(false), isOpen = _e[0], setIsOpen = _e[1];
@@ -151,12 +173,11 @@ var IconPicker = function (_a) {
151
173
  parentRef.current.scrollTop = 0;
152
174
  }
153
175
  }, [setSearch]);
154
- var renderIcon = useCallback(function (icon) { return (_jsx(Button, { variant: "roundedWhite", size: "icon", onClick: function () { return handleIconClick(icon.name); }, children: _jsx(IconRenderer, { name: icon.name }) }, icon.name)); }, [handleIconClick]);
155
- return (_jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [_jsx(PopoverTrigger, __assign({ asChild: true }, props, { children: children || (_jsxs(Button, { variant: "white", className: className, children: [value || selectedIcon ? (_jsx(IconRenderer, { name: (value || selectedIcon) })) : null, chooseIconLabel || "Select icon"] })) })), _jsxs(PopoverContent, { className: "w-64 h-70 flex flex-col overflow-hidden p-0", children: [searchable && (_jsx("div", { className: "m-4 mb-2", children: _jsx(Input, { placeholder: searchPlaceholder, onChange: handleSearchChange }) })), _jsx("div", { ref: parentRef, className: "overflow-auto flex-1 p-4 pt-2", style: { scrollbarWidth: "thin" }, onWheel: function (e) {
176
+ var renderIcon = useCallback(function (icon) { return (_jsx(Button, { variant: "roundedWhite", size: "icon", onClick: function () { return handleIconClick(icon.name); }, children: _jsx(DynamicIcon, { name: icon.name }) }, icon.name)); }, [handleIconClick]);
177
+ return (_jsxs(Popover, { open: isOpen, onOpenChange: setIsOpen, children: [_jsx(PopoverTrigger, __assign({ asChild: true }, props, { children: children || (_jsxs(Button, { variant: "white", className: className, children: [value || selectedIcon ? (_jsx(DynamicIcon, { name: (value || selectedIcon) })) : null, chooseIconLabel || "Select icon"] })) })), _jsxs(PopoverContent, { className: "w-64 h-70 flex flex-col overflow-hidden p-0", children: [searchable && (_jsx("div", { className: "m-4 mb-2", children: _jsx(Input, { placeholder: searchPlaceholder, onChange: handleSearchChange }) })), _jsx("div", { ref: parentRef, className: "overflow-auto flex-1 p-4 pt-2", style: { scrollbarWidth: "thin" }, onWheel: function (e) {
156
178
  e.stopPropagation();
157
179
  }, onTouchMove: function (e) {
158
180
  e.stopPropagation();
159
181
  }, children: isLoading ? (_jsx(IconsColumnSkeleton, {})) : (_jsx("div", { className: "grid grid-cols-5 gap-2 w-full", children: filteredIcons.map(renderIcon) })) })] })] }));
160
182
  };
161
183
  IconPicker.displayName = "IconPicker";
162
- export { IconPicker };
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@examplary/ui",
3
3
  "description": "UI components for the Examplary testing platform.",
4
4
  "packageManager": "yarn@4.5.3",
5
- "version": "1.39.0",
5
+ "version": "1.39.1",
6
6
  "type": "module",
7
7
  "main": "dist/index.js",
8
8
  "files": [
@@ -10,7 +10,7 @@
10
10
  "src/global.css"
11
11
  ],
12
12
  "scripts": {
13
- "start": "yarn build --watch",
13
+ "dev": "yarn build --watch",
14
14
  "release": "semantic-release -e semantic-release-monorepo",
15
15
  "build": "yarn build:js && yarn build:styles",
16
16
  "build:js": "tsc ./src/index.ts --outDir dist --skipLibCheck --declaration --jsx react-jsx --esModuleInterop --moduleResolution bundler --module es2020",