@zuzjs/ui 0.9.7 → 0.9.82

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 (82) hide show
  1. package/dist/cjs/comps/Calendar/index.d.ts +3 -0
  2. package/dist/cjs/comps/Calendar/index.js +109 -0
  3. package/dist/cjs/comps/Calendar/types.d.ts +6 -0
  4. package/dist/cjs/comps/Calendar/types.js +1 -0
  5. package/dist/cjs/comps/Crumb/index.d.ts +1 -1
  6. package/dist/cjs/comps/DatePicker/index.d.ts +11 -0
  7. package/dist/cjs/comps/DatePicker/index.js +73 -0
  8. package/dist/cjs/comps/DatePicker/types.d.ts +6 -0
  9. package/dist/cjs/comps/DatePicker/types.js +1 -0
  10. package/dist/cjs/comps/Icon/index.d.ts +2 -0
  11. package/dist/cjs/comps/Icon/index.js +5 -2
  12. package/dist/cjs/comps/List/index.d.ts +1 -1
  13. package/dist/cjs/comps/Select/optionItem.d.ts +2 -1
  14. package/dist/cjs/comps/Select/optionItem.js +3 -2
  15. package/dist/cjs/comps/Select/types.d.ts +2 -0
  16. package/dist/cjs/comps/Table/index.js +2 -2
  17. package/dist/cjs/comps/Table/row.js +2 -2
  18. package/dist/cjs/comps/Table/types.d.ts +2 -0
  19. package/dist/cjs/comps/TextArea/commands.d.ts +12 -0
  20. package/dist/cjs/comps/TextArea/commands.js +16 -0
  21. package/dist/cjs/comps/TextArea/index.d.ts +13 -6
  22. package/dist/cjs/comps/TextArea/index.js +88 -6
  23. package/dist/cjs/comps/TextArea/types.d.ts +21 -0
  24. package/dist/cjs/comps/TextArea/types.js +1 -0
  25. package/dist/cjs/comps/index.d.ts +5 -1
  26. package/dist/cjs/comps/index.js +3 -0
  27. package/dist/cjs/comps/svgicons.d.ts +1 -0
  28. package/dist/cjs/comps/svgicons.js +1 -0
  29. package/dist/cjs/funs/index.d.ts +5 -0
  30. package/dist/cjs/funs/index.js +42 -0
  31. package/dist/cjs/funs/stylesheet.js +1 -0
  32. package/dist/cjs/hooks/index.d.ts +2 -0
  33. package/dist/cjs/hooks/index.js +2 -0
  34. package/dist/cjs/hooks/useCommandActions.d.ts +29 -0
  35. package/dist/cjs/hooks/useCommandActions.js +104 -0
  36. package/dist/cjs/hooks/usePosition.d.ts +2 -1
  37. package/dist/cjs/hooks/usePushNotifications.d.ts +45 -0
  38. package/dist/cjs/hooks/usePushNotifications.js +166 -0
  39. package/dist/cjs/hooks/useSlider.d.ts +1 -1
  40. package/dist/css/styles.css +1 -1
  41. package/dist/esm/comps/Calendar/index.d.ts +3 -0
  42. package/dist/esm/comps/Calendar/index.js +109 -0
  43. package/dist/esm/comps/Calendar/types.d.ts +6 -0
  44. package/dist/esm/comps/Calendar/types.js +1 -0
  45. package/dist/esm/comps/Crumb/index.d.ts +1 -1
  46. package/dist/esm/comps/DatePicker/index.d.ts +11 -0
  47. package/dist/esm/comps/DatePicker/index.js +73 -0
  48. package/dist/esm/comps/DatePicker/types.d.ts +6 -0
  49. package/dist/esm/comps/DatePicker/types.js +1 -0
  50. package/dist/esm/comps/Icon/index.d.ts +2 -0
  51. package/dist/esm/comps/Icon/index.js +5 -2
  52. package/dist/esm/comps/List/index.d.ts +1 -1
  53. package/dist/esm/comps/Select/optionItem.d.ts +2 -1
  54. package/dist/esm/comps/Select/optionItem.js +3 -2
  55. package/dist/esm/comps/Select/types.d.ts +2 -0
  56. package/dist/esm/comps/Table/index.js +2 -2
  57. package/dist/esm/comps/Table/row.js +2 -2
  58. package/dist/esm/comps/Table/types.d.ts +2 -0
  59. package/dist/esm/comps/TextArea/commands.d.ts +12 -0
  60. package/dist/esm/comps/TextArea/commands.js +16 -0
  61. package/dist/esm/comps/TextArea/index.d.ts +13 -6
  62. package/dist/esm/comps/TextArea/index.js +88 -6
  63. package/dist/esm/comps/TextArea/types.d.ts +21 -0
  64. package/dist/esm/comps/TextArea/types.js +1 -0
  65. package/dist/esm/comps/index.d.ts +5 -1
  66. package/dist/esm/comps/index.js +3 -0
  67. package/dist/esm/comps/svgicons.d.ts +1 -0
  68. package/dist/esm/comps/svgicons.js +1 -0
  69. package/dist/esm/funs/index.d.ts +5 -0
  70. package/dist/esm/funs/index.js +42 -0
  71. package/dist/esm/funs/stylesheet.js +1 -0
  72. package/dist/esm/hooks/index.d.ts +2 -0
  73. package/dist/esm/hooks/index.js +2 -0
  74. package/dist/esm/hooks/useCommandActions.d.ts +29 -0
  75. package/dist/esm/hooks/useCommandActions.js +104 -0
  76. package/dist/esm/hooks/usePosition.d.ts +2 -1
  77. package/dist/esm/hooks/usePushNotifications.d.ts +45 -0
  78. package/dist/esm/hooks/usePushNotifications.js +166 -0
  79. package/dist/esm/hooks/useSlider.d.ts +1 -1
  80. package/dist/tsconfig.esm.tsbuildinfo +1 -1
  81. package/dist/tsconfig.tsbuildinfo +1 -1
  82. package/package.json +2 -1
@@ -4,9 +4,12 @@ import { useBase } from "../../hooks";
4
4
  import { Size } from "../../types/enums";
5
5
  import Span from "../Span";
6
6
  const Icon = forwardRef((props, ref) => {
7
- const { name, pathCount, size, ...pops } = props;
7
+ const { name, pathCount, size, color, ...pops } = props;
8
8
  const { className, style, rest } = useBase(pops);
9
- return _jsx("div", { style: style, className: `icon-${name} --icon --${size || Size.Default} ${className}`.trim(), ref: ref, ...rest, children: Array(pathCount || 0).fill(0).map((p, i) => _jsx(Span, { className: `path${i + 1}` }, `${name}-layer-${i}`)) });
9
+ return _jsx("div", { style: {
10
+ color,
11
+ ...style,
12
+ }, className: `icon-${name} --icon --${size || Size.Default} ${className}`.trim(), ref: ref, ...rest, children: Array(pathCount || 0).fill(0).map((p, i) => _jsx(Span, { className: `path${i + 1}` }, `${name}-layer-${i}`)) });
10
13
  });
11
14
  Icon.displayName = `Zuz.Icon`;
12
15
  export default Icon;
@@ -6,5 +6,5 @@ declare const List: import("react").ForwardRefExoticComponent<import("../..").Zu
6
6
  direction?: "cols" | "rows";
7
7
  seperator?: import("react").ReactNode;
8
8
  ol?: boolean;
9
- } & import("react").RefAttributes<HTMLOListElement | HTMLUListElement>>;
9
+ } & import("react").RefAttributes<HTMLUListElement | HTMLOListElement>>;
10
10
  export default List;
@@ -1,6 +1,7 @@
1
+ import React from "react";
1
2
  import { OptionItemProps } from "./types";
2
3
  declare const OptionItem: {
3
- ({ value, updateValue, o }: OptionItemProps): import("react/jsx-runtime").JSX.Element;
4
+ ({ value, updateValue, o }: OptionItemProps): React.ReactElement;
4
5
  displayName: string;
5
6
  };
6
7
  export default OptionItem;
@@ -1,7 +1,8 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Icon, Text } from "..";
2
3
  import Button from "../Button";
3
4
  const OptionItem = ({ value, updateValue, o }) => {
4
- return _jsx(Button, { onClick: (e) => updateValue(o), className: value && (`string` == typeof o ? o : o.value) == (`string` == typeof value ? value : value.value) ? `selected` : ``, children: `string` == typeof o ? o : o.label });
5
+ return _jsxs(Button, { onClick: (e) => updateValue(o), as: `--select-option-item`, className: value && (`string` == typeof o ? o : o.value) == (`string` == typeof value ? value : value.value) ? `selected` : ``, children: [o.icon && _jsx(Icon, { name: o.icon, as: `--select-option-icon --icon-${o.value}`, color: o.iconColor || undefined }), _jsx(Text, { children: `string` == typeof o ? o : o.label })] });
5
6
  };
6
7
  OptionItem.displayName = `Option`;
7
8
  export default OptionItem;
@@ -5,6 +5,8 @@ import { BoxProps } from "../Box";
5
5
  * Represents an option which can be either a string or an OptionObject.
6
6
  */
7
7
  export type Option = {
8
+ icon?: string | ReactNode;
9
+ iconColor?: string;
8
10
  label: string;
9
11
  value: string;
10
12
  };
@@ -63,7 +63,7 @@ import TRow from "./row";
63
63
  * ```
64
64
  */
65
65
  const Table = (props, ref) => {
66
- const { schema, rows, rowCount, rowsPerPage, currentPage, pagination, paginationHash, showPaginationOnZeroPageCount, animateRows, header, rowClassName, selectableRows, hoverable, sortBy, loading: _loading, loadingRowCount, loadingMessage, spinner, emptyMessage, onSort, onRowSelectToggle, onPageChange, onRowContextMenu, ...pops } = props;
66
+ const { schema, rows, rowCount, rowsPerPage, currentPage, pagination, paginationHash, showPaginationOnZeroPageCount, animateRows, header, rowClassName, selectableRows, hoverable, sortBy, loading: _loading, loadingRowCount, loadingMessage, spinner, emptyMessage, onSort, onRowClick, onRowSelectToggle, onPageChange, onRowContextMenu, ...pops } = props;
67
67
  const _pagination = useRef(null);
68
68
  const _schemaParsed = useMemo(() => schema.reduce((prev, c) => {
69
69
  prev[c.id] = {
@@ -117,7 +117,7 @@ const Table = (props, ref) => {
117
117
  // _loading.current = mod
118
118
  }
119
119
  }));
120
- return _jsxs(Box, { as: `--table ${(hoverable ?? true) ? `--hoverable` : ``} flex cols rel ${className}`, ref: _tableRef, children: [_header == true && _jsx(TRow, { sortBy: _sortBy, onSort: handleSort, tableRef: _tableRef, pubsub: pubsub, selectable: selectableRows, index: -1, schema: schema, loading: true, styles: _schemaParsed }), _loading && _jsxs(Box, { as: `center-x flex aic --table-spinner`, children: [_jsx(Spinner, { type: spinner || SPINNER.Simple }), _loadingMessage && _jsx(Text, { as: `--table-loading-message`, children: _loadingMessage })] }), _loading && Array(loadingRowCount || 5).fill({}).map((row, index) => _jsx(TRow, { tableRef: _tableRef, index: index, pubsub: pubsub, schema: schema, styles: _schemaParsed, loading: true, animate: animateRows }, `--trow-loading-${index}-${schema[0].id}`)), !_loading && rows && rows.map((row, index) => _jsx(TRow, { tableRef: _tableRef, pubsub: pubsub, loading: false, index: index, schema: schema, ids: _cols, styles: _schemaParsed, animate: animateRows, data: row, rowClassName: rowClassName, selectable: selectableRows, onSelect: onRowSelectToggle, onContextMenu: onRowContextMenu }, `--trow-${rowKeys.current[index] || index}-${schema[0].id}`)), isEmpty && renderEmpty(), _jsx(Box, { "aria-hidden": !pagination || !_paginated, ...(animateRows ? { fx: {
120
+ return _jsxs(Box, { as: `--table ${(hoverable ?? true) ? `--hoverable` : ``} flex cols rel ${className}`, ref: _tableRef, children: [_header == true && _jsx(TRow, { sortBy: _sortBy, onSort: handleSort, tableRef: _tableRef, pubsub: pubsub, selectable: selectableRows, index: -1, schema: schema, loading: true, styles: _schemaParsed }), _loading && _jsxs(Box, { as: `center-x flex aic --table-spinner`, children: [_jsx(Spinner, { type: spinner || SPINNER.Simple }), _loadingMessage && _jsx(Text, { as: `--table-loading-message`, children: _loadingMessage })] }), _loading && Array(loadingRowCount || 5).fill({}).map((row, index) => _jsx(TRow, { tableRef: _tableRef, index: index, pubsub: pubsub, schema: schema, styles: _schemaParsed, loading: true, animate: animateRows, onRowClick: onRowClick }, `--trow-loading-${index}-${schema[0].id}`)), !_loading && rows && rows.map((row, index) => _jsx(TRow, { tableRef: _tableRef, pubsub: pubsub, loading: false, index: index, schema: schema, ids: _cols, styles: _schemaParsed, animate: animateRows, data: row, onRowClick: onRowClick, rowClassName: rowClassName, selectable: selectableRows, onSelect: onRowSelectToggle, onContextMenu: onRowContextMenu }, `--trow-${rowKeys.current[index] || index}-${schema[0].id}`)), isEmpty && renderEmpty(), _jsx(Box, { "aria-hidden": !pagination || !_paginated, ...(animateRows ? { fx: {
121
121
  transition: TRANSITIONS.SlideInBottom,
122
122
  curve: TRANSITION_CURVES.EaseInOut,
123
123
  delay: .02 * (rows.length + 1),
@@ -7,7 +7,7 @@ import CheckBox from "../CheckBox";
7
7
  import Text from "../Text";
8
8
  import TColumn from "./col";
9
9
  const TRow = (props) => {
10
- const { index, pubsub, schema, data, ids, styles, animate, sortBy, selectable, tableRef, loading, rowClassName, onSort, onSelect, onContextMenu } = props;
10
+ const { index, pubsub, schema, data, ids, styles, animate, sortBy, selectable, tableRef, loading, rowClassName, onSort, onRowClick, onSelect, onContextMenu } = props;
11
11
  const mounted = useDelayed();
12
12
  const _animation = useMemo(() => ({
13
13
  transition: TRANSITIONS.SlideInBottom,
@@ -74,7 +74,7 @@ const TRow = (props) => {
74
74
  };
75
75
  }
76
76
  }, []);
77
- return _jsxs(Box, { onContextMenu: e => onContextMenu ? onContextMenu(e, data) : null, ...(animate ? { fx: { ..._animation, when: mounted } } : {}), as: `--row flex aic ${index == -1 ? `--row-head` : ``} ${rowClassName || ``}`, children: [index == -1 && schema.map((c, i) => {
77
+ return _jsxs(Box, { onContextMenu: e => onContextMenu ? onContextMenu(e, data) : null, onClick: e => onRowClick ? onRowClick(e, props.data) : () => { }, ...(animate ? { fx: { ..._animation, when: mounted } } : {}), as: `--row flex aic ${onRowClick ? `--row-clickable` : ``} ${index == -1 ? `--row-head` : ``} ${rowClassName || ``}`, children: [index == -1 && schema.map((c, i) => {
78
78
  const { renderWhenHeader, render, value, ...cc } = c;
79
79
  return _jsxs(Fragment, { children: [selectable && i == 0 && Selector(-1, `--selector-${c.id}`, `all`), _jsx(TColumn, { idx: -1, onSort: onSort, sortBy: sortBy,
80
80
  // value={renderWhenHeader && render ? render!(index == -1 ? c as dynamicObject : data as T, index) : value as string}
@@ -53,6 +53,7 @@ export type Row<T> = {
53
53
  sortBy?: string | null;
54
54
  onSelect?: RowSelectCallback<T>;
55
55
  onSort?: TableSortCallback;
56
+ onRowClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, row: T) => void;
56
57
  pubsub: PubSub;
57
58
  loading: boolean;
58
59
  tableRef?: RefObject<HTMLDivElement | null>;
@@ -145,6 +146,7 @@ export type TableProps<T> = BoxProps & {
145
146
  spinner?: SPINNER;
146
147
  emptyMessage?: ReactNode | FC;
147
148
  onRowSelectToggle?: RowSelectCallback<T>;
149
+ onRowClick?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, row: T) => void;
148
150
  onRowContextMenu?: (e: React.MouseEvent<HTMLDivElement, MouseEvent>, row: T) => void;
149
151
  onPageChange?: PaginationCallback;
150
152
  onSort?: TableSortCallback;
@@ -0,0 +1,12 @@
1
+ import { FC } from "react";
2
+ import { Command } from "../..";
3
+ declare const CommandBox: FC<{
4
+ position: {
5
+ top: number;
6
+ left: number;
7
+ };
8
+ commands: Command[];
9
+ visible: boolean;
10
+ onSelect: (value: string) => void;
11
+ }>;
12
+ export default CommandBox;
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Button, Icon, Text, TRANSITIONS } from "../..";
3
+ import Box from "../Box";
4
+ const CommandItem = ({ meta }) => {
5
+ return _jsxs(Button, { as: `flex aic --command-item`, children: [meta.icon && _jsx(Icon, { name: meta.icon, as: `--command-icon` }), _jsx(Text, { children: meta.label })] });
6
+ };
7
+ const CommandBox = ({ position, onSelect, commands, visible }) => {
8
+ return _jsx(Box, { "aria-hidden": !visible, fx: {
9
+ transition: TRANSITIONS.SlideInBottom,
10
+ duration: 0.1,
11
+ when: visible
12
+ }, className: `--command-box abs grid`, style: {
13
+ ...position
14
+ }, children: commands.map(c => _jsx(CommandItem, { meta: c }, `cmd-${c.label.replace(/\s+/, '-')}`)) });
15
+ };
16
+ export default CommandBox;
@@ -1,13 +1,20 @@
1
- import { Props } from '../../types';
2
1
  import { Variant } from '../../types/enums';
3
- export type TextAreaProps = Props<`textarea`> & {
4
- autoResize?: boolean;
5
- resize?: `none` | `block` | `both` | `horizontal` | `vertical`;
6
- variant?: Variant;
7
- };
8
2
  declare const TextArea: import("react").ForwardRefExoticComponent<import("../..").ZuzProps & Omit<Omit<import("react").DetailedHTMLProps<import("react").TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>, "ref">, keyof import("../..").ZuzProps> & {
9
3
  autoResize?: boolean;
10
4
  resize?: `none` | `block` | `both` | `horizontal` | `vertical`;
5
+ maxHeight?: number | string;
11
6
  variant?: Variant;
7
+ command?: string;
8
+ commands?: import("../..").Command[];
9
+ cmd?: (value: string, textarea: HTMLTextAreaElement | HTMLInputElement) => void;
10
+ renderDropdown?: (props: {
11
+ show: boolean;
12
+ position: {
13
+ top: number;
14
+ left: number;
15
+ };
16
+ commands: import("../..").Command[];
17
+ onSelect: (value: string) => void;
18
+ }) => React.ReactNode;
12
19
  } & import("react").RefAttributes<HTMLTextAreaElement>>;
13
20
  export default TextArea;
@@ -1,13 +1,95 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { forwardRef } from 'react';
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { forwardRef, useCallback, useEffect, useRef } from 'react';
3
+ import { Box, useCommandActions } from "../..";
3
4
  import { useBase } from '../../hooks';
4
5
  import { Variant } from '../../types/enums';
6
+ import CommandBox from "./commands";
5
7
  const TextArea = forwardRef((props, ref) => {
6
- const { autoResize, variant, resize, ...pops } = props;
8
+ const { autoResize, maxHeight, variant = Variant.Small, resize = 'none', command, commands, onInput, cmd, renderDropdown, value: controlledValue, defaultValue, ...pops } = props;
9
+ const innerRef = useRef(null);
10
+ const frameRef = useRef(null);
7
11
  const { style, className, rest } = useBase(pops);
8
- const handleInput = (event) => {
12
+ const { showDropdown, dropdownPosition, handleKeyDown, handleInput: handleCommandInput, handleCommandSelect, } = useCommandActions({
13
+ command,
14
+ commands,
15
+ cmd,
16
+ ref: innerRef,
17
+ });
18
+ // ------------------------------------------------------------------
19
+ // Resize function (no state → direct DOM update)
20
+ // ------------------------------------------------------------------
21
+ const resizeTextArea = useCallback(() => {
22
+ const textarea = innerRef.current;
23
+ if (!textarea || !autoResize)
24
+ return;
25
+ // Cancel previous frame
26
+ if (frameRef.current) {
27
+ cancelAnimationFrame(frameRef.current);
28
+ }
29
+ // Schedule resize after paint
30
+ frameRef.current = requestAnimationFrame(() => {
31
+ textarea.style.height = 'auto';
32
+ let newHeight = textarea.scrollHeight;
33
+ if (maxHeight) {
34
+ const max = parseInt(maxHeight.toString(), 10);
35
+ if (!isNaN(max)) {
36
+ newHeight = Math.min(newHeight, max);
37
+ }
38
+ }
39
+ textarea.style.height = `${newHeight}px`;
40
+ textarea.style.overflowY = maxHeight && newHeight >= parseInt(maxHeight.toString(), 10) ? 'auto' : 'hidden';
41
+ });
42
+ }, [autoResize, maxHeight]);
43
+ // ------------------------------------------------------------------
44
+ // Input handler
45
+ // ------------------------------------------------------------------
46
+ const handleInput = (e) => {
47
+ onInput?.(e);
48
+ handleCommandInput(e);
49
+ resizeTextArea();
9
50
  };
10
- return _jsx("textarea", { className: `--input --textarea --${variant || Variant.Small} flex ${className}`.trim(), style: { ...style, resize: resize || `none` }, onInput: handleInput, ref: ref, ...rest });
51
+ // ------------------------------------------------------------------
52
+ // Initial resize + controlled value change
53
+ // ------------------------------------------------------------------
54
+ useEffect(() => {
55
+ resizeTextArea();
56
+ }, [controlledValue, defaultValue, resizeTextArea]);
57
+ // ------------------------------------------------------------------
58
+ // Resize on mount
59
+ // ------------------------------------------------------------------
60
+ useEffect(() => {
61
+ if (autoResize && innerRef.current) {
62
+ resizeTextArea();
63
+ }
64
+ }, [autoResize, resizeTextArea]);
65
+ // ------------------------------------------------------------------
66
+ // Cleanup
67
+ // ------------------------------------------------------------------
68
+ useEffect(() => {
69
+ return () => {
70
+ if (frameRef.current) {
71
+ cancelAnimationFrame(frameRef.current);
72
+ }
73
+ };
74
+ }, []);
75
+ return (_jsxs(Box, { as: "rel", children: [_jsx("textarea", { className: `--input --textarea --${variant} flex ${className}`.trim(), style: {
76
+ ...style,
77
+ resize,
78
+ height: autoResize ? 'auto' : style?.height,
79
+ overflow: 'hidden', // Always hidden unless maxHeight hit
80
+ transition: autoResize ? 'none' : undefined, // Remove transition flicker
81
+ }, onKeyDown: handleKeyDown, onInput: handleInput, ref: (node) => {
82
+ if (typeof ref === 'function')
83
+ ref(node);
84
+ else if (ref)
85
+ ref.current = node;
86
+ innerRef.current = node;
87
+ }, value: controlledValue, defaultValue: defaultValue, ...rest }), renderDropdown ? (renderDropdown({
88
+ show: showDropdown,
89
+ position: dropdownPosition,
90
+ commands: commands || [],
91
+ onSelect: handleCommandSelect,
92
+ })) : (commands && commands.length > 0 && (_jsx(CommandBox, { visible: showDropdown, commands: commands, onSelect: handleCommandSelect, position: dropdownPosition })))] }));
11
93
  });
12
- TextArea.displayName = `Zuz.TextArea`;
94
+ TextArea.displayName = 'Zuz.TextArea';
13
95
  export default TextArea;
@@ -0,0 +1,21 @@
1
+ import { Command } from "../..";
2
+ import { Props } from '../../types';
3
+ import { Variant } from '../../types/enums';
4
+ export type TextAreaProps = Props<`textarea`> & {
5
+ autoResize?: boolean;
6
+ resize?: `none` | `block` | `both` | `horizontal` | `vertical`;
7
+ maxHeight?: number | string;
8
+ variant?: Variant;
9
+ command?: string;
10
+ commands?: Command[];
11
+ cmd?: (value: string, textarea: HTMLTextAreaElement | HTMLInputElement) => void;
12
+ renderDropdown?: (props: {
13
+ show: boolean;
14
+ position: {
15
+ top: number;
16
+ left: number;
17
+ };
18
+ commands: Command[];
19
+ onSelect: (value: string) => void;
20
+ }) => React.ReactNode;
21
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -12,6 +12,8 @@ export * from './Avatar/types';
12
12
  export { default as Box, type BoxProps } from './Box';
13
13
  export { default as Button } from './Button';
14
14
  export * from './Button/types';
15
+ export { default as Calendar } from './Calendar';
16
+ export * from './Calendar/types';
15
17
  export { default as Chart } from './Chart';
16
18
  export * from './Chart/types';
17
19
  export { default as CheckBox } from './CheckBox';
@@ -26,6 +28,7 @@ export { default as Cropper } from './Cropper';
26
28
  export * from './Cropper/types';
27
29
  export { default as Crumb } from './Crumb';
28
30
  export * from './Crumb/types';
31
+ export { default as DatePicker } from './DatePicker';
29
32
  export { default as Drawer } from './Drawer';
30
33
  export * from './Drawer/types';
31
34
  /**Editor */
@@ -78,7 +81,8 @@ export * from './Table/types';
78
81
  export { default as TabView } from './TabView';
79
82
  export * from './TabView/types';
80
83
  export { default as Text, type TextProps } from './Text';
81
- export { default as Textarea, type TextAreaProps } from './TextArea';
84
+ export { default as Textarea } from './TextArea';
85
+ export { type TextAreaProps } from './TextArea/types';
82
86
  export { default as TextWheel } from './TextWheel';
83
87
  export * from './TextWheel/types';
84
88
  export { default as ToastProvider } from './Toast';
@@ -12,6 +12,8 @@ export * from './Avatar/types';
12
12
  export { default as Box } from './Box';
13
13
  export { default as Button } from './Button';
14
14
  export * from './Button/types';
15
+ export { default as Calendar } from './Calendar';
16
+ export * from './Calendar/types';
15
17
  export { default as Chart } from './Chart';
16
18
  export * from './Chart/types';
17
19
  export { default as CheckBox } from './CheckBox';
@@ -26,6 +28,7 @@ export { default as Cropper } from './Cropper';
26
28
  export * from './Cropper/types';
27
29
  export { default as Crumb } from './Crumb';
28
30
  export * from './Crumb/types';
31
+ export { default as DatePicker } from './DatePicker';
29
32
  export { default as Drawer } from './Drawer';
30
33
  export * from './Drawer/types';
31
34
  /**Editor */
@@ -31,5 +31,6 @@ declare const SVGIcons: {
31
31
  bezier: import("react/jsx-runtime").JSX.Element;
32
32
  mouse: import("react/jsx-runtime").JSX.Element;
33
33
  addKey: import("react/jsx-runtime").JSX.Element;
34
+ calendar: import("react/jsx-runtime").JSX.Element;
34
35
  };
35
36
  export default SVGIcons;
@@ -34,6 +34,7 @@ const SVGIcons = {
34
34
  bezier: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "100%", height: "100%", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M19.14 7.72C19.43 8.47 20.15 9 21 9C22.1 9 23 8.1 23 7C23 5.9 22.1 5 21 5C20.15 5 19.43 5.53 19.14 6.28C19.09 6.27 19.05 6.25 19 6.25H15V5.5C15 4.68 14.32 4 13.5 4H10.5C9.68 4 9 4.68 9 5.5V6.25H5C4.95 6.25 4.91 6.27 4.86 6.28C4.57 5.53 3.85 5 3 5C1.9 5 1 5.9 1 7C1 8.1 1.9 9 3 9C3.85 9 4.57 8.47 4.86 7.72C4.91 7.73 4.95 7.75 5 7.75H7.57C5.52 9.27 4.25 11.79 4.25 14.5C4.25 14.67 4.26 14.83 4.28 15H4C3.17 15 2.5 15.67 2.5 16.5V18.5C2.5 19.33 3.17 20 4 20H6C6.22 20 6.42 19.95 6.61 19.86C7.13 19.64 7.5 19.11 7.5 18.5V16.5C7.5 15.67 6.83 15 6 15H5.77C5.77 14.97 5.78 14.94 5.78 14.91C5.76 14.77 5.76 14.64 5.76 14.5C5.76 12.03 7.03 9.77 9.02 8.6C9.06 9.37 9.71 10 10.5 10H13.5C14.29 10 14.94 9.37 14.99 8.6C16.98 9.77 18.25 12.04 18.25 14.5C18.25 14.64 18.24 14.77 18.23 14.91C18.23 14.94 18.24 14.97 18.24 15H18C17.17 15 16.5 15.67 16.5 16.5V18.5C16.5 19.11 16.87 19.64 17.39 19.86C17.58 19.95 17.78 20 18 20H20C20.83 20 21.5 19.33 21.5 18.5V16.5C21.5 15.67 20.83 15 20 15H19.72C19.74 14.83 19.75 14.67 19.75 14.5C19.75 11.79 18.48 9.27 16.43 7.75H19C19.05 7.75 19.09 7.73 19.14 7.72Z", fill: "#292D32" }) }),
35
35
  mouse: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "100%", height: "100%", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M13.2978 2.11468C13.0064 2.06339 12.75 2.29593 12.75 2.59185V5.45262C12.75 5.65098 12.8709 5.82564 13.0359 5.93583C13.5391 6.27202 13.87 6.84597 13.87 7.49906V9.49906C13.87 10.5291 13.03 11.3791 12 11.3791C10.96 11.3791 10.12 10.5291 10.12 9.49906V7.49906C10.12 6.84578 10.4583 6.27168 10.9639 5.93554C11.1291 5.82572 11.25 5.65098 11.25 5.45262V2.59249C11.25 2.29634 10.9935 2.0637 10.7019 2.11513C9.15243 2.38834 7.76579 3.13327 6.7 4.19906C5.34 5.55906 4.5 7.43906 4.5 9.49906V14.4991C4.5 18.6291 7.87 21.9991 12 21.9991C16.13 21.9991 19.5 18.6291 19.5 14.4991V9.49906C19.5 5.80857 16.813 2.73328 13.2978 2.11468Z", fill: "#292D32" }) }),
36
36
  addKey: _jsx("svg", { xmlns: "http://www.w3.org/2000/svg", width: "100%", height: "100%", viewBox: "0 0 24 24", fill: "none", children: _jsx("path", { d: "M20.9498 14.55L14.5598 20.94C13.1598 22.34 10.8598 22.34 9.44977 20.94L3.05977 14.55C1.65977 13.15 1.65977 10.85 3.05977 9.44L9.44977 3.05C10.8498 1.65 13.1498 1.65 14.5598 3.05L20.9498 9.44C22.3498 10.85 22.3498 13.15 20.9498 14.55Z", fill: "#292D32" }) }),
37
+ calendar: _jsxs("svg", { xmlns: "http://www.w3.org/2000/svg", fill: "none", viewBox: "0 0 24 24", children: [_jsx("path", { fill: "#292D32", d: "M8.25 5.75c-.41 0-.75-.34-.75-.75V2c0-.41.34-.75.75-.75S9 1.59 9 2v3c0 .41-.34.75-.75.75M15.75 5.75c-.41 0-.75-.34-.75-.75V2c0-.41.34-.75.75-.75s.75.34.75.75v3c0 .41-.34.75-.75.75M12 14.09c.52 0 .9-.31.9-.8 0-.5-.38-.79-.9-.79s-.9.29-.9.79c0 .49.38.8.9.8M12 17c.629 0 1.14-.416 1.14-.93 0-.513-.511-.93-1.14-.93-.63 0-1.14.417-1.14.93s.51.93 1.14.93" }), _jsx("path", { fill: "#292D32", d: "M19.57 4.5c-.66-.49-1.61-.02-1.61.81v.1c0 1.17-.84 2.25-2.01 2.37-1.35.14-2.49-.92-2.49-2.24V4.5c0-.55-.45-1-1-1h-.92c-.55 0-1 .45-1 1v1.04c0 .79-.41 1.49-1.03 1.88-.09.06-.19.11-.29.16q-.135.075-.3.12c-.12.04-.25.07-.39.08q-.24.03-.48 0c-.14-.01-.27-.04-.39-.08q-.15-.045-.3-.12c-.1-.05-.2-.1-.29-.16-.63-.44-1.03-1.2-1.03-2.01v-.1c0-.77-.82-1.23-1.47-.9-.01.01-.02.01-.03.02-.04.02-.07.04-.11.07-.03.03-.07.05-.1.08-.28.22-.53.47-.74.74-.11.12-.2.25-.28.38a3.498 3.498 0 0 0-.27.46c-.02.02-.03.03-.03.05-.06.12-.12.24-.16.37-.03.05-.04.09-.06.14-.06.15-.1.3-.14.45-.04.14-.07.29-.09.44a5.902 5.902 0 0 0-.06.76v8.76A4.87 4.87 0 0 0 7.37 22h9.26a4.87 4.87 0 0 0 4.87-4.87V8.37c0-1.59-.76-2.98-1.93-3.87M12 18.25c-1.55 0-2.5-.77-2.5-2.01 0-.68.35-1.27.96-1.62-.44-.31-.73-.77-.73-1.4 0-1.3 1.04-1.97 2.27-1.97s2.26.67 2.26 1.97c0 .63-.28 1.09-.73 1.4.62.35.97.94.97 1.62 0 1.24-.96 2.01-2.5 2.01" })] }),
37
38
  // animation: <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24">
38
39
  // <path fill="#292D32" d="m15.39 5.211 1.41 2.82c.19.39.7.76 1.13.84l2.55.42c1.63.27 2.01 1.45.84 2.63l-1.99 1.99c-.33.33-.52.98-.41 1.45l.57 2.46c.45 1.94-.59 2.7-2.3 1.68l-2.39-1.42c-.43-.26-1.15-.26-1.58 0l-2.39 1.42c-1.71 1.01-2.75.26-2.3-1.68l.57-2.46c.09-.48-.1-1.13-.43-1.46l-1.99-1.99c-1.17-1.17-.79-2.35.84-2.63l2.55-.42c.43-.07.94-.45 1.13-.84l1.41-2.82c.77-1.52 2.01-1.52 2.78.01M8 5.75H2c-.41 0-.75-.34-.75-.75s.34-.75.75-.75h6c.41 0 .75.34.75.75s-.34.75-.75.75M5 19.75H2c-.41 0-.75-.34-.75-.75s.34-.75.75-.75h3c.41 0 .75.34.75.75s-.34.75-.75.75M3 12.75H2c-.41 0-.75-.34-.75-.75s.34-.75.75-.75h1c.41 0 .75.34.75.75s-.34.75-.75.75" />
39
40
  // </svg>,
@@ -77,3 +77,8 @@ export declare const checkPasswordStrength: (password: string) => {
77
77
  result: string;
78
78
  suggestion: string[];
79
79
  };
80
+ export declare const getCaretCoordinates: (element: HTMLTextAreaElement, position: number) => {
81
+ top: number;
82
+ left: number;
83
+ };
84
+ export declare const urlBase64ToUint8Array: (base64String: string) => Uint8Array;
@@ -502,3 +502,45 @@ export const checkPasswordStrength = (password) => {
502
502
  suggestion: suggestions
503
503
  };
504
504
  };
505
+ export const getCaretCoordinates = (element, position) => {
506
+ const div = document.createElement('div');
507
+ const style = window.getComputedStyle(element);
508
+ const properties = [
509
+ 'fontFamily', 'fontSize', 'fontWeight', 'letterSpacing',
510
+ 'lineHeight', 'paddingLeft', 'paddingTop', 'borderLeftWidth',
511
+ 'borderTopWidth', 'boxSizing', 'width', 'height', 'overflow'
512
+ ];
513
+ // Copy styles to temporary div
514
+ properties.forEach(prop => {
515
+ div.style.setProperty(prop, style.getPropertyValue(prop));
516
+ });
517
+ div.style.position = 'absolute';
518
+ div.style.visibility = 'hidden';
519
+ div.style.whiteSpace = 'pre-wrap';
520
+ div.style.wordWrap = 'break-word';
521
+ div.textContent = element.value.substring(0, position);
522
+ // Append a span to measure caret position
523
+ const span = document.createElement('span');
524
+ span.textContent = element.value.substring(position) || ' ';
525
+ div.appendChild(span);
526
+ document.body.appendChild(div);
527
+ // Get coordinates
528
+ const rect = span.getBoundingClientRect();
529
+ const textareaRect = element.getBoundingClientRect();
530
+ const coordinates = {
531
+ top: rect.top - textareaRect.top + element.scrollTop,
532
+ left: rect.left - textareaRect.left + element.scrollLeft,
533
+ };
534
+ document.body.removeChild(div);
535
+ return coordinates;
536
+ };
537
+ export const urlBase64ToUint8Array = (base64String) => {
538
+ const padding = '='.repeat((4 - base64String.length % 4) % 4);
539
+ const base64 = (base64String + padding).replace(/-/g, '+').replace(/_/g, '/');
540
+ const rawData = window.atob(base64);
541
+ const outputArray = new Uint8Array(rawData.length);
542
+ for (let i = 0; i < rawData.length; ++i) {
543
+ outputArray[i] = rawData.charCodeAt(i);
544
+ }
545
+ return outputArray;
546
+ };
@@ -257,6 +257,7 @@ export const cssProps = {
257
257
  "backdropFilter": "backdrop-filter",
258
258
  "placeItems": "place-items",
259
259
  "placeContent": "place-content",
260
+ "corner": "corner-shape",
260
261
  };
261
262
  export const cssDirect = {
262
263
  "extend": "@extend __VALUE__;",
@@ -2,6 +2,7 @@ export { default as useAnchorPosition } from './useAnchorPosition';
2
2
  export { default as useBase } from './useBase';
3
3
  export { default as useCalendar } from './useCalendar';
4
4
  export { useColorScheme } from './useColorScheme';
5
+ export { default as useCommandActions, type Command, type CommandActionProps } from './useCommandActions';
5
6
  export { default as useContextMenu } from './useContextMenu';
6
7
  export { default as useDB, type IDBOptions, type IDBSchema } from './useDB';
7
8
  export { default as useDebounce } from './useDebounce';
@@ -28,6 +29,7 @@ export { default as useSheet } from './useSheet';
28
29
  export { default as useShortcuts } from './useShortcuts';
29
30
  export { default as useNetworkStatus } from './useNetworkStatus';
30
31
  export { default as usePosition } from './usePosition';
32
+ export { default as usePushNotifications, type PushNotificationsOptions, type PushNotificationsResult, type PushSubscriptionMeta } from './usePushNotifications';
31
33
  export { default as useResizeObserver } from './useResizeObserver';
32
34
  export { default as useSlider } from './useSlider';
33
35
  export { default as useToast } from './useToast';
@@ -2,6 +2,7 @@ export { default as useAnchorPosition } from './useAnchorPosition';
2
2
  export { default as useBase } from './useBase';
3
3
  export { default as useCalendar } from './useCalendar';
4
4
  export { useColorScheme } from './useColorScheme';
5
+ export { default as useCommandActions } from './useCommandActions';
5
6
  export { default as useContextMenu } from './useContextMenu';
6
7
  export { default as useDB } from './useDB';
7
8
  export { default as useDebounce } from './useDebounce';
@@ -29,6 +30,7 @@ export { default as useSheet } from './useSheet';
29
30
  export { default as useShortcuts } from './useShortcuts';
30
31
  export { default as useNetworkStatus } from './useNetworkStatus';
31
32
  export { default as usePosition } from './usePosition';
33
+ export { default as usePushNotifications } from './usePushNotifications';
32
34
  export { default as useResizeObserver } from './useResizeObserver';
33
35
  export { default as useSlider } from './useSlider';
34
36
  export { default as useToast } from './useToast';
@@ -0,0 +1,29 @@
1
+ import { RefObject } from "react";
2
+ export type Command = {
3
+ label: string;
4
+ value: string;
5
+ icon?: string;
6
+ type?: 'command' | 'submenu' | 'action';
7
+ subCommands?: Command[];
8
+ action?: React.ReactNode | ((props: {
9
+ onSelect: (value: string) => void;
10
+ }) => React.ReactNode);
11
+ };
12
+ export type CommandActionProps = {
13
+ command?: string;
14
+ commands?: Command[];
15
+ cmd?: (value: string, textarea: HTMLTextAreaElement | HTMLInputElement) => void;
16
+ ref: RefObject<HTMLTextAreaElement | HTMLInputElement | null>;
17
+ };
18
+ declare const useCommandActions: ({ command, commands, cmd, ref, }: CommandActionProps) => {
19
+ showDropdown: boolean;
20
+ dropdownPosition: {
21
+ top: number;
22
+ left: number;
23
+ };
24
+ handleKeyDown: (event: React.KeyboardEvent<HTMLTextAreaElement | HTMLInputElement>) => void;
25
+ handleInput: (event: React.FormEvent<HTMLTextAreaElement | HTMLInputElement>) => void;
26
+ handleCommandSelect: (value: string) => void;
27
+ parentRef: RefObject<HTMLDivElement | null>;
28
+ };
29
+ export default useCommandActions;
@@ -0,0 +1,104 @@
1
+ import { useEffect } from "react";
2
+ import { useState } from "react";
3
+ import { useRef } from "react";
4
+ const useCommandActions = ({ command = '/', commands = [], cmd, ref, }) => {
5
+ const [commandStart, setCommandStart] = useState(-1);
6
+ const [showDropdown, setShowDropdown] = useState(false);
7
+ const [dropdownPosition, setDropdownPosition] = useState({ top: 0, left: 0 });
8
+ const parentRef = useRef(null);
9
+ const handleInput = (event) => {
10
+ const textarea = ref.current;
11
+ if (textarea && showDropdown) {
12
+ const { value } = textarea;
13
+ if (commandStart < 0 || commandStart >= value.length || value[commandStart] !== command) {
14
+ setShowDropdown(false);
15
+ }
16
+ }
17
+ };
18
+ const handleKeyDown = (event) => {
19
+ const textarea = ref.current;
20
+ if (!textarea)
21
+ return;
22
+ const { selectionStart } = textarea;
23
+ if (event.key === command) {
24
+ setCommandStart(selectionStart || -1);
25
+ const caretPos = getCaretCoordinates(textarea, selectionStart || -1);
26
+ setDropdownPosition({
27
+ top: caretPos.top + 20,
28
+ left: caretPos.left,
29
+ });
30
+ setShowDropdown(true);
31
+ }
32
+ else if (event.key === 'Escape') {
33
+ event.preventDefault();
34
+ event.stopPropagation();
35
+ setShowDropdown(false);
36
+ }
37
+ };
38
+ const handleCommandSelect = (value) => {
39
+ const textarea = ref.current;
40
+ if (!textarea)
41
+ return;
42
+ if (cmd) {
43
+ cmd(value, textarea);
44
+ }
45
+ else {
46
+ const { value: currentValue, selectionStart } = textarea;
47
+ const newValue = currentValue.slice(0, commandStart) +
48
+ value +
49
+ currentValue.slice(selectionStart || -1);
50
+ textarea.value = newValue;
51
+ textarea.setSelectionRange(commandStart + value.length, commandStart + value.length);
52
+ const event = new Event('input', { bubbles: true });
53
+ textarea.dispatchEvent(event);
54
+ }
55
+ setShowDropdown(false);
56
+ textarea.focus();
57
+ };
58
+ const getCaretCoordinates = (element, position) => {
59
+ const canvas = document.createElement('canvas');
60
+ const context = canvas.getContext('2d');
61
+ if (!context) {
62
+ return { top: 0, left: 0 };
63
+ }
64
+ const style = window.getComputedStyle(element);
65
+ context.font = `${style.fontSize} ${style.fontFamily}`;
66
+ const text = element.value.substring(0, position);
67
+ const lines = text.split('\n');
68
+ const lastLine = lines[lines.length - 1];
69
+ const left = context.measureText(lastLine).width;
70
+ const lineHeight = parseFloat(style.lineHeight) || parseFloat(style.fontSize) * 1.2;
71
+ const top = (lines.length - 1) * lineHeight;
72
+ const paddingTop = parseFloat(style.paddingTop) || 0;
73
+ const paddingLeft = parseFloat(style.paddingLeft) || 0;
74
+ const scrollTop = element.scrollTop;
75
+ canvas.remove();
76
+ return {
77
+ top: top - scrollTop + paddingTop,
78
+ left: left + paddingLeft,
79
+ };
80
+ };
81
+ useEffect(() => {
82
+ const handleClickOutside = (event) => {
83
+ if (ref.current &&
84
+ parentRef.current &&
85
+ !ref.current.contains(event.target) &&
86
+ !parentRef.current.contains(event.target)) {
87
+ setShowDropdown(false);
88
+ }
89
+ };
90
+ document.addEventListener('mousedown', handleClickOutside);
91
+ return () => {
92
+ document.removeEventListener('mousedown', handleClickOutside);
93
+ };
94
+ }, [ref]);
95
+ return {
96
+ showDropdown,
97
+ dropdownPosition,
98
+ handleKeyDown,
99
+ handleInput,
100
+ handleCommandSelect,
101
+ parentRef,
102
+ };
103
+ };
104
+ export default useCommandActions;
@@ -5,7 +5,8 @@ interface PositionOptions {
5
5
  container?: HTMLElement | null;
6
6
  triggerRef?: React.RefObject<HTMLElement>;
7
7
  }
8
- export declare const usePosition: (ref: React.RefObject<HTMLElement>, options?: PositionOptions) => {
8
+ export declare const usePosition: (ref: React.RefObject<HTMLElement>, // The element to be positioned
9
+ options?: PositionOptions) => {
9
10
  postion: "fixed" | "absolute" | null;
10
11
  reposition: () => void;
11
12
  };