@node-core/ui-components 1.5.0 → 1.5.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.
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
2
- .badge{text-align:center;white-space:nowrap;color:var(--color-white,#fff);border-radius:3.40282e38px}.badge.small{padding-inline:calc(var(--spacing,.25rem)*1.5);padding-block:calc(var(--spacing,.25rem)*0.5);font-size:var(--text-xs,.75rem);line-height:var(--tw-leading,var(--text-xs--line-height,1.33333))}.badge.medium{padding-inline:calc(var(--spacing,.25rem)*2.5);padding-block:calc(var(--spacing,.25rem)*0.5);font-size:var(--text-base,1rem);line-height:var(--tw-leading,var(--text-base--line-height,1.5))}.badge.default{background-color:var(--color-green-600,#417e38)}.badge.error{background-color:var(--color-danger-600,#de1a1b)}.badge.warning{background-color:var(--color-warning-600,#ae5f00)}.badge.info{background-color:var(--color-info-600,#0c7bb3)}.badge.neutral{background-color:var(--color-neutral-600,#929fa5)}
2
+ .badge{text-align:center;white-space:nowrap;color:var(--color-white,#fff);border-radius:3.40282e38px}.badge.small{padding-inline:calc(var(--spacing,.25rem)*1.5);padding-block:calc(var(--spacing,.25rem)*0.5);font-size:var(--text-xs,.75rem);line-height:var(--tw-leading,var(--text-xs--line-height,1.33333))}.badge.medium{padding-inline:calc(var(--spacing,.25rem)*2.5);padding-block:calc(var(--spacing,.25rem)*0.5);font-size:var(--text-base,1rem);line-height:var(--tw-leading,var(--text-base--line-height,1.5))}.badge.default{background-color:var(--color-green-600,#417e38)}.badge.error{background-color:var(--color-danger-600,#de1a1b)}.badge.warning{background-color:var(--color-warning-600,#ae5f00)}.badge.info{background-color:var(--color-info-600,#0c7bb3)}.badge.neutral{background-color:var(--color-neutral-800,#556066)}
@@ -1,8 +1,10 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import { DocumentDuplicateIcon, CodeBracketIcon, } from '@heroicons/react/24/outline';
3
4
  import classNames from 'classnames';
4
5
  import { Fragment, isValidElement, useRef } from 'react';
5
6
  import BaseButton from '#ui/Common/BaseButton';
7
+ import useCopy from '#ui/hooks/useCopy';
6
8
  import styles from './index.module.css';
7
9
  // Transforms a code element with plain text content into a more structured
8
10
  // format for rendering with line numbers
@@ -36,14 +38,11 @@ const transformCode = (code, language) => {
36
38
  // the last flatMap entry which is an `\n`
37
39
  .slice(0, -2) }));
38
40
  };
39
- const BaseCodeBox = ({ children, language, className, onCopy, buttonContent, as = 'a', }) => {
41
+ const BaseCodeBox = ({ children, language, className, copyButtonLabel, copiedButtonLabel, as = 'a', }) => {
42
+ const [copied, copy] = useCopy();
40
43
  const containerRef = useRef(null);
41
- const handleCopy = () => {
42
- const text = containerRef.current?.textContent;
43
- if (text) {
44
- onCopy(text);
45
- }
46
- };
47
- return (_jsxs("div", { className: styles.root, children: [_jsx("pre", { ref: containerRef, className: classNames(styles.content, className), tabIndex: 0, children: transformCode(children, language) }), language && (_jsxs("div", { className: styles.footer, children: [_jsx("span", { className: styles.language, children: language }), _jsx(BaseButton, { as: as, className: styles.action, kind: "neutral", onClick: handleCopy, children: buttonContent })] }))] }));
44
+ const handleCopy = () => copy(containerRef.current?.textContent);
45
+ const ButtonIcon = copied ? DocumentDuplicateIcon : CodeBracketIcon;
46
+ return (_jsxs("div", { className: styles.root, children: [_jsx("pre", { ref: containerRef, className: classNames(styles.content, className), tabIndex: 0, children: transformCode(children, language) }), language && (_jsxs("div", { className: styles.footer, children: [_jsx("span", { className: styles.language, children: language }), _jsxs(BaseButton, { as: as, className: styles.action, kind: "neutral", onClick: handleCopy, children: [_jsx(ButtonIcon, { className: "size-4" }), copied ? copiedButtonLabel : copyButtonLabel] })] }))] }));
48
47
  };
49
48
  export default BaseCodeBox;
@@ -1,2 +1,2 @@
1
1
  /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
2
- .link{text-overflow:ellipsis;white-space:nowrap;max-width:fit-content;overflow:hidden}.link.active{background-color:var(--color-green-600,#417e38);padding-inline:calc(var(--spacing,.25rem)*2);padding-block:calc(var(--spacing,.25rem)*1);--tw-font-weight:var(--font-weight-semibold,600);font-weight:var(--font-weight-semibold,600);color:var(--color-white,#fff);border-radius:.25rem}@media (prefers-reduced-motion:no-preference){.link.active{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4,0,.2,1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s))}}.link.active:where([data-theme=dark],[data-theme=dark] *){color:var(--color-white,#fff)}.link.active:hover{background-color:var(--color-green-700,#2c682c);color:var(--color-white,#fff)}@property --tw-font-weight{syntax:"*";inherits:false}
2
+ .link{text-overflow:ellipsis;white-space:nowrap;max-width:fit-content;overflow:hidden}.link.active{background-color:var(--color-green-800,#2c682c);padding-inline:calc(var(--spacing,.25rem)*2);padding-block:calc(var(--spacing,.25rem)*1);--tw-font-weight:var(--font-weight-semibold,600);font-weight:var(--font-weight-semibold,600);color:var(--color-white,#fff);border-radius:.25rem}@media (prefers-reduced-motion:no-preference){.link.active{transition-property:color,background-color,border-color,outline-color,text-decoration-color,fill,stroke,--tw-gradient-from,--tw-gradient-via,--tw-gradient-to;transition-timing-function:var(--tw-ease,var(--default-transition-timing-function,cubic-bezier(.4,0,.2,1)));transition-duration:var(--tw-duration,var(--default-transition-duration,.15s))}}.link.active:where([data-theme=dark],[data-theme=dark] *){color:var(--color-white,#fff)}.link.active:hover{background-color:var(--color-green-700,#2c682c);color:var(--color-white,#fff)}@property --tw-font-weight{syntax:"*";inherits:false}
@@ -2,23 +2,11 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ChevronDownIcon } from '@heroicons/react/24/solid';
3
3
  import classNames from 'classnames';
4
4
  import { useId, useMemo } from 'react';
5
- import { isStringArray, isValuesArray } from '#ui/util/array';
5
+ import { mapValues } from '../utils';
6
6
  import styles from '../index.module.css';
7
7
  const StatelessSelect = ({ values = [], defaultValue, placeholder, label, inline, className, ariaLabel, disabled = false, as: Component = 'div', }) => {
8
8
  const id = useId();
9
- const mappedValues = useMemo(() => {
10
- let mappedValues = values;
11
- if (isStringArray(mappedValues)) {
12
- mappedValues = mappedValues.map(value => ({
13
- label: value,
14
- value,
15
- }));
16
- }
17
- if (isValuesArray(mappedValues)) {
18
- return [{ items: mappedValues }];
19
- }
20
- return mappedValues;
21
- }, [values]);
9
+ const mappedValues = useMemo(() => mapValues(values), [values]);
22
10
  // Find the current/default item to display in summary
23
11
  const currentItem = useMemo(() => mappedValues
24
12
  .flatMap(({ items }) => items)
@@ -5,25 +5,13 @@ import * as SelectPrimitive from '@radix-ui/react-select';
5
5
  import classNames from 'classnames';
6
6
  import { useEffect, useId, useMemo, useState } from 'react';
7
7
  import Skeleton from '#ui/Common/Skeleton';
8
- import { isStringArray, isValuesArray } from '#ui/util/array';
8
+ import { mapValues } from './utils';
9
9
  import styles from './index.module.css';
10
10
  const Select = ({ values = [], defaultValue, placeholder, label, inline, onChange, className, dropdownClassName, ariaLabel, loading = false, disabled = false, fallbackClass = '', }) => {
11
11
  const id = useId();
12
12
  const [value, setValue] = useState(defaultValue);
13
13
  useEffect(() => setValue(defaultValue), [defaultValue]);
14
- const mappedValues = useMemo(() => {
15
- let mappedValues = values;
16
- if (isStringArray(mappedValues)) {
17
- mappedValues = mappedValues.map(value => ({
18
- label: value,
19
- value,
20
- }));
21
- }
22
- if (isValuesArray(mappedValues)) {
23
- return [{ items: mappedValues }];
24
- }
25
- return mappedValues;
26
- }, [values]);
14
+ const mappedValues = useMemo(() => mapValues(values), [values]);
27
15
  // We render the actual item slotted to fix/prevent the issue
28
16
  // of the tirgger flashing on the initial render
29
17
  const currentItem = useMemo(() => mappedValues
@@ -0,0 +1,15 @@
1
+ export const isStringArray = (values) => Boolean(values[0] && typeof values[0] === 'string');
2
+ export const isValuesArray = (values) => Boolean(values[0] && typeof values[0] === 'object' && 'value' in values[0]);
3
+ export const mapValues = (values) => {
4
+ let mappedValues = values;
5
+ if (isStringArray(mappedValues)) {
6
+ mappedValues = mappedValues.map(value => ({
7
+ label: value,
8
+ value,
9
+ }));
10
+ }
11
+ if (isValuesArray(mappedValues)) {
12
+ return [{ items: mappedValues }];
13
+ }
14
+ return mappedValues;
15
+ };
@@ -0,0 +1,6 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import styles from './index.module.css';
3
+ const SkipToContentButton = ({ children, href = '#main', ...props }) => {
4
+ return (_jsx("a", { href: href, className: styles.skipToContent, ...props, children: children }));
5
+ };
6
+ export default SkipToContentButton;
@@ -0,0 +1,2 @@
1
+ /*! tailwindcss v4.1.18 | MIT License | https://tailwindcss.com */
2
+ .skipToContent{clip-path:inset(50%);white-space:nowrap;border-width:0;width:1px;height:1px;margin:-1px;padding:0;position:absolute;overflow:hidden}.skipToContent:focus{clip-path:none;white-space:normal;width:auto;height:auto;top:calc(var(--spacing,.25rem)*4);left:calc(var(--spacing,.25rem)*4);z-index:50;background-color:var(--color-green-600,#417e38);padding:0;padding-inline:calc(var(--spacing,.25rem)*4);padding-block:calc(var(--spacing,.25rem)*2);color:var(--color-white,#fff);--tw-ring-shadow:var(--tw-ring-inset,)0 0 0 calc(2px + var(--tw-ring-offset-width))var(--tw-ring-color,currentcolor);box-shadow:var(--tw-inset-shadow),var(--tw-inset-ring-shadow),var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow);--tw-ring-color:var(--color-green-500,#5fa04e);--tw-outline-style:none;border-radius:.25rem;outline-style:none;margin:0;position:absolute;overflow:visible}.skipToContent:where([data-theme=dark],[data-theme=dark] *):focus{--tw-ring-color:var(--color-green-400,#84ba64)}@property --tw-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-shadow-color{syntax:"*";inherits:false}@property --tw-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-inset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-shadow-color{syntax:"*";inherits:false}@property --tw-inset-shadow-alpha{syntax:"<percentage>";inherits:false;initial-value:100%}@property --tw-ring-color{syntax:"*";inherits:false}@property --tw-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-inset-ring-color{syntax:"*";inherits:false}@property --tw-inset-ring-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}@property --tw-ring-inset{syntax:"*";inherits:false}@property --tw-ring-offset-width{syntax:"<length>";inherits:false;initial-value:0}@property --tw-ring-offset-color{syntax:"*";inherits:false;initial-value:#fff}@property --tw-ring-offset-shadow{syntax:"*";inherits:false;initial-value:0 0 #0000}
@@ -0,0 +1,28 @@
1
+ import { useCallback, useEffect, useState } from 'react';
2
+ const copyToClipboard = async (value) => {
3
+ if (!value) {
4
+ return false;
5
+ }
6
+ try {
7
+ await navigator.clipboard.writeText(value);
8
+ return true;
9
+ }
10
+ catch {
11
+ return false;
12
+ }
13
+ };
14
+ export default function useCopy() {
15
+ const [copied, setCopied] = useState(false);
16
+ const copyText = useCallback(async (text) => {
17
+ const success = await copyToClipboard(text);
18
+ setCopied(success);
19
+ }, []);
20
+ useEffect(() => {
21
+ if (!copied) {
22
+ return;
23
+ }
24
+ const timerId = setTimeout(() => setCopied(false), 3000);
25
+ return () => clearTimeout(timerId);
26
+ }, [copied]);
27
+ return [copied, copyText];
28
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@node-core/ui-components",
3
- "version": "1.5.0",
3
+ "version": "1.5.1",
4
4
  "type": "module",
5
5
  "repository": {
6
6
  "type": "git",
package/util/array.js DELETED
@@ -1,2 +0,0 @@
1
- export const isStringArray = (values) => Boolean(values[0] && typeof values[0] === 'string');
2
- export const isValuesArray = (values) => Boolean(values[0] && typeof values[0] === 'object' && 'value' in values[0]);