@jirawatpyk/aura-react 4.4.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.
@@ -0,0 +1,192 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { useStrings, useAuraLocale } from "./locale.js";
4
+ import { createPortal } from "react-dom";
5
+ import { cx, uid, useMounted, useIsoLayoutEffect, useMergedRef } from "./internal.js";
6
+ import { Icon } from "./Icon.js";
7
+ import { IconButton } from "./IconButton.js";
8
+ const h = React.createElement;
9
+ var ALERT_ICON = { info: "info", success: "circle-check", warning: "triangle-alert", danger: "circle-alert" };
10
+ const Alert = React.forwardRef(function Alert2(props, ref) {
11
+ var t = useStrings();
12
+ var tone = props.tone || "info";
13
+ return h(
14
+ "div",
15
+ {
16
+ ref,
17
+ className: cx("aura-alert", "aura-alert--" + tone, props.className),
18
+ role: tone === "danger" || tone === "warning" ? "alert" : "status"
19
+ },
20
+ h(Icon, { name: ALERT_ICON[tone], className: "aura-alert__icon" }),
21
+ h(
22
+ "div",
23
+ { className: "aura-alert__body" },
24
+ props.title ? h("p", { className: "aura-alert__title" }, props.title) : null,
25
+ props.children ? h("div", { className: "aura-alert__text" }, props.children) : null,
26
+ props.action ? h("div", { className: "aura-alert__action" }, props.action) : null
27
+ ),
28
+ props.onDismiss ? h(IconButton, { icon: "x", label: t.dismiss, className: "aura-alert__close", onClick: props.onDismiss }) : null
29
+ );
30
+ });
31
+ var toastState = { list: [], subs: [], n: 0 };
32
+ function emitToasts() {
33
+ toastState.subs.forEach(function(f) {
34
+ f(toastState.list.slice());
35
+ });
36
+ }
37
+ function toast(opts) {
38
+ if (typeof opts === "string") opts = { title: opts };
39
+ var id = opts.id || "t" + ++toastState.n;
40
+ toastState.list = toastState.list.filter(function(t) {
41
+ return t.id !== id;
42
+ }).concat([Object.assign({ tone: "info" }, opts, { id })]).slice(-3);
43
+ emitToasts();
44
+ return id;
45
+ }
46
+ toast.dismiss = function(id) {
47
+ toastState.list = toastState.list.filter(function(t) {
48
+ return t.id !== id;
49
+ });
50
+ emitToasts();
51
+ };
52
+ function ToastItem(props) {
53
+ var str = useStrings();
54
+ var t = props.toast, timer = React.useRef(null), left = React.useRef(t.duration || 5e3), since = React.useRef(0);
55
+ function start() {
56
+ if (left.current === Infinity) return;
57
+ since.current = Date.now();
58
+ timer.current = setTimeout(function() {
59
+ toast.dismiss(t.id);
60
+ }, left.current);
61
+ }
62
+ function pause() {
63
+ if (timer.current) {
64
+ clearTimeout(timer.current);
65
+ timer.current = null;
66
+ left.current -= Date.now() - since.current;
67
+ }
68
+ }
69
+ React.useEffect(function() {
70
+ start();
71
+ return pause;
72
+ }, []);
73
+ return h(
74
+ "div",
75
+ {
76
+ className: cx("aura-toast", "aura-toast--" + t.tone),
77
+ role: t.tone === "danger" ? "alert" : "status",
78
+ onMouseEnter: pause,
79
+ onMouseLeave: start,
80
+ onFocus: pause,
81
+ onBlur: start
82
+ },
83
+ h(Icon, { name: ALERT_ICON[t.tone] || "info", className: "aura-toast__icon" }),
84
+ h(
85
+ "div",
86
+ { className: "aura-toast__body" },
87
+ h("p", { className: "aura-toast__title" }, t.title),
88
+ t.description ? h("p", { className: "aura-toast__text" }, t.description) : null
89
+ ),
90
+ t.action ? h("button", {
91
+ type: "button",
92
+ className: "aura-toast__action",
93
+ onClick: function() {
94
+ t.action.onClick && t.action.onClick();
95
+ toast.dismiss(t.id);
96
+ }
97
+ }, t.action.label) : null,
98
+ h(IconButton, { icon: "x", label: str.dismissToast, className: "aura-toast__close", onClick: function() {
99
+ toast.dismiss(t.id);
100
+ } })
101
+ );
102
+ }
103
+ function Toaster(props) {
104
+ var t = useStrings();
105
+ var mounted = useMounted();
106
+ var s = React.useState(toastState.list);
107
+ React.useEffect(function() {
108
+ toastState.subs.push(s[1]);
109
+ return function() {
110
+ toastState.subs = toastState.subs.filter(function(f) {
111
+ return f !== s[1];
112
+ });
113
+ };
114
+ }, []);
115
+ if (!mounted) return null;
116
+ return createPortal(h(
117
+ "div",
118
+ { className: cx("aura-toaster", props && props.position === "top" && "is-top"), role: "region", "aria-live": "polite", "aria-label": t.notifications },
119
+ s[0].map(function(t2) {
120
+ return h(ToastItem, { key: t2.id, toast: t2 });
121
+ })
122
+ ), document.body);
123
+ }
124
+ const Tooltip = React.forwardRef(function Tooltip2(props, ref) {
125
+ var id = uid(), st = React.useState(false), open = props.open !== void 0 ? props.open : st[0], set = st[1];
126
+ var anchor = React.useRef(null), anchorMerged = useMergedRef(ref, anchor), tip = React.useRef(null), timer = React.useRef(null);
127
+ var pos = React.useState(null);
128
+ function show(now) {
129
+ clearTimeout(timer.current);
130
+ timer.current = setTimeout(function() {
131
+ set(true);
132
+ }, now ? 0 : props.delay == null ? 400 : props.delay);
133
+ }
134
+ function hide() {
135
+ clearTimeout(timer.current);
136
+ set(false);
137
+ }
138
+ useIsoLayoutEffect(function() {
139
+ if (!open || !anchor.current || !tip.current) return;
140
+ var r = anchor.current.getBoundingClientRect(), t = tip.current.getBoundingClientRect();
141
+ var side = props.side || "top", top = side === "top" ? r.top - t.height - 8 : r.bottom + 8;
142
+ if (side === "top" && top < 8) top = r.bottom + 8;
143
+ var left = Math.max(8, Math.min(r.left + r.width / 2 - t.width / 2, window.innerWidth - t.width - 8));
144
+ pos[1]({ top, left });
145
+ }, [open]);
146
+ React.useEffect(function() {
147
+ if (!open) return;
148
+ function esc(e) {
149
+ if (e.key === "Escape") hide();
150
+ }
151
+ document.addEventListener("keydown", esc);
152
+ return function() {
153
+ document.removeEventListener("keydown", esc);
154
+ };
155
+ }, [open]);
156
+ var child = React.Children.only(props.children);
157
+ var trigger = h(
158
+ "span",
159
+ {
160
+ ref: anchorMerged,
161
+ className: "aura-tooltip-anchor",
162
+ onMouseEnter: function() {
163
+ show(false);
164
+ },
165
+ onMouseLeave: hide,
166
+ onFocus: function() {
167
+ show(true);
168
+ },
169
+ onBlur: hide
170
+ },
171
+ React.cloneElement(child, { "aria-describedby": open ? id : child.props["aria-describedby"] })
172
+ );
173
+ return h(
174
+ React.Fragment,
175
+ null,
176
+ trigger,
177
+ open ? createPortal(h("div", {
178
+ ref: tip,
179
+ id,
180
+ role: "tooltip",
181
+ className: "aura-tooltip",
182
+ style: { top: pos[0] ? pos[0].top : -9999, left: pos[0] ? pos[0].left : -9999 }
183
+ }, props.content), document.body) : null
184
+ );
185
+ });
186
+ export {
187
+ ALERT_ICON,
188
+ Alert,
189
+ Toaster,
190
+ Tooltip,
191
+ toast
192
+ };
@@ -0,0 +1,181 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ import { useStrings } from "./locale.js";
4
+ import { cx, omit, useMaybeControlled, uid } from "./internal.js";
5
+ import { Icon } from "./Icon.js";
6
+ const h = React.createElement;
7
+ const Field = React.forwardRef(function Field2(props, ref) {
8
+ var t = useStrings();
9
+ return h(
10
+ "div",
11
+ { ref, className: cx("aura-field", props.error && "is-invalid", props.disabled && "is-disabled", props.className) },
12
+ props.label ? h(
13
+ props.labelAs || "label",
14
+ { className: "aura-field__label", htmlFor: props.labelAs ? void 0 : props.id, id: props.labelId },
15
+ props.label,
16
+ props.required ? h("span", { className: "aura-field__req", "aria-hidden": true }, " *") : null,
17
+ props.optional ? h("span", { className: "aura-field__opt" }, " (" + t.optional + ")") : null
18
+ ) : null,
19
+ props.children,
20
+ props.error ? h("p", { className: "aura-field__error", id: props.id + "-error" }, h(Icon, { name: "circle-alert", size: 14 }), props.error) : props.hint ? h("p", { className: "aura-field__hint", id: props.id + "-hint" }, props.hint) : null
21
+ );
22
+ });
23
+ function describedBy(id, p) {
24
+ return p.error ? id + "-error" : p.hint ? id + "-hint" : void 0;
25
+ }
26
+ var FIELD_KEYS = ["label", "hint", "error", "required", "optional", "icon", "className", "id", "suffix", "options", "placeholder"];
27
+ const TextField = React.forwardRef(function TextField2(props, ref) {
28
+ var auto = uid(), id = props.id || auto;
29
+ var rest = omit(props, FIELD_KEYS);
30
+ return h(
31
+ Field,
32
+ { id, label: props.label, hint: props.hint, error: props.error, required: props.required, optional: props.optional, disabled: props.disabled, className: props.className },
33
+ h(
34
+ "div",
35
+ { className: cx("aura-input", props.icon && "has-icon", props.suffix && "has-suffix") },
36
+ props.icon ? h(Icon, { name: props.icon, className: "aura-input__icon" }) : null,
37
+ h("input", Object.assign({ type: "text" }, rest, {
38
+ ref,
39
+ id,
40
+ className: "aura-input__control",
41
+ placeholder: props.placeholder,
42
+ required: props.required,
43
+ "aria-invalid": props.error ? true : void 0,
44
+ "aria-describedby": describedBy(id, props)
45
+ })),
46
+ props.suffix ? h("span", { className: "aura-input__suffix" }, props.suffix) : null
47
+ )
48
+ );
49
+ });
50
+ const Textarea = React.forwardRef(function Textarea2(props, ref) {
51
+ var auto = uid(), id = props.id || auto;
52
+ var rest = omit(props, FIELD_KEYS);
53
+ return h(
54
+ Field,
55
+ { id, label: props.label, hint: props.hint, error: props.error, required: props.required, optional: props.optional, disabled: props.disabled, className: props.className },
56
+ h("textarea", Object.assign({ rows: 4 }, rest, {
57
+ ref,
58
+ id,
59
+ className: "aura-input aura-textarea",
60
+ placeholder: props.placeholder,
61
+ required: props.required,
62
+ "aria-invalid": props.error ? true : void 0,
63
+ "aria-describedby": describedBy(id, props)
64
+ }))
65
+ );
66
+ });
67
+ const Select = React.forwardRef(function Select2(props, ref) {
68
+ var auto = uid(), id = props.id || auto;
69
+ var rest = omit(props, FIELD_KEYS.concat(["children"]));
70
+ var opts = (props.options || []).map(function(o) {
71
+ var v = typeof o === "object" ? o : { value: o, label: o };
72
+ return h("option", { key: v.value, value: v.value, disabled: v.disabled }, v.label);
73
+ });
74
+ if (props.placeholder) opts.unshift(h("option", { key: "__ph", value: "", disabled: true }, props.placeholder));
75
+ var extra = props.value === void 0 && props.defaultValue === void 0 && props.placeholder ? { defaultValue: "" } : {};
76
+ return h(
77
+ Field,
78
+ { id, label: props.label, hint: props.hint, error: props.error, required: props.required, optional: props.optional, disabled: props.disabled, className: props.className },
79
+ h(
80
+ "div",
81
+ { className: cx("aura-input aura-select", props.icon && "has-icon") },
82
+ props.icon ? h(Icon, { name: props.icon, className: "aura-input__icon" }) : null,
83
+ h("select", Object.assign(extra, rest, {
84
+ ref,
85
+ id,
86
+ className: "aura-input__control",
87
+ required: props.required,
88
+ "aria-invalid": props.error ? true : void 0,
89
+ "aria-describedby": describedBy(id, props)
90
+ }), opts, props.children),
91
+ h(Icon, { name: "chevron-down", className: "aura-select__chevron" })
92
+ )
93
+ );
94
+ });
95
+ const RadioGroup = React.forwardRef(function RadioGroup2(props, ref) {
96
+ var auto = uid(), id = props.id || auto;
97
+ var st = useMaybeControlled(props.value, props.defaultValue, props.onChange);
98
+ var name = props.name || id;
99
+ return h(
100
+ "fieldset",
101
+ {
102
+ ref,
103
+ className: cx("aura-field aura-radio-group", props.error && "is-invalid", props.className),
104
+ "aria-describedby": describedBy(id, props),
105
+ "aria-invalid": props.error ? true : void 0,
106
+ disabled: props.disabled
107
+ },
108
+ props.label ? h("legend", { className: "aura-field__label" }, props.label, props.required ? h("span", { className: "aura-field__req", "aria-hidden": true }, " *") : null) : null,
109
+ h(
110
+ "div",
111
+ { className: cx("aura-radio-group__list", props.orientation === "horizontal" && "is-horizontal") },
112
+ (props.options || []).map(function(o) {
113
+ var v = typeof o === "object" ? o : { value: o, label: o };
114
+ return h(
115
+ "label",
116
+ { key: v.value, className: cx("aura-choice", v.disabled && "is-disabled") },
117
+ h("input", {
118
+ type: "radio",
119
+ className: "aura-radio",
120
+ name,
121
+ value: v.value,
122
+ disabled: v.disabled,
123
+ checked: st[0] === v.value,
124
+ onChange: function() {
125
+ st[1](v.value);
126
+ }
127
+ }),
128
+ h(
129
+ "span",
130
+ { className: "aura-choice__text" },
131
+ h("span", { className: "aura-choice__label" }, v.label),
132
+ v.description ? h("span", { className: "aura-choice__desc" }, v.description) : null
133
+ )
134
+ );
135
+ })
136
+ ),
137
+ props.error ? h("p", { className: "aura-field__error", id: id + "-error" }, h(Icon, { name: "circle-alert", size: 14 }), props.error) : props.hint ? h("p", { className: "aura-field__hint", id: id + "-hint" }, props.hint) : null
138
+ );
139
+ });
140
+ const Switch = React.forwardRef(function Switch2(props, ref) {
141
+ var auto = uid(), id = props.id || auto;
142
+ var st = useMaybeControlled(props.checked, !!props.defaultChecked, props.onChange);
143
+ var on = !!st[0];
144
+ return h(
145
+ "div",
146
+ { className: cx("aura-switch-row", props.disabled && "is-disabled", props.className) },
147
+ h(
148
+ "button",
149
+ {
150
+ ref,
151
+ type: "button",
152
+ role: "switch",
153
+ id,
154
+ "aria-checked": on,
155
+ disabled: props.disabled,
156
+ "aria-labelledby": props.label ? id + "-label" : void 0,
157
+ "aria-label": props.label ? void 0 : props["aria-label"],
158
+ "aria-describedby": props.description ? id + "-desc" : void 0,
159
+ className: cx("aura-switch", on && "is-on"),
160
+ onClick: function() {
161
+ st[1](!on);
162
+ }
163
+ },
164
+ h("span", { className: "aura-switch__thumb" })
165
+ ),
166
+ props.label ? h(
167
+ "span",
168
+ { className: "aura-choice__text" },
169
+ h("label", { className: "aura-choice__label", id: id + "-label", htmlFor: id }, props.label),
170
+ props.description ? h("span", { className: "aura-choice__desc", id: id + "-desc" }, props.description) : null
171
+ ) : null
172
+ );
173
+ });
174
+ export {
175
+ Field,
176
+ RadioGroup,
177
+ Select,
178
+ Switch,
179
+ TextField,
180
+ Textarea
181
+ };
@@ -0,0 +1,89 @@
1
+ 'use client';
2
+ import { Icon, iconNames, ICONS } from "./Icon.js";
3
+ import { Button } from "./Button.js";
4
+ import { IconButton } from "./IconButton.js";
5
+ import { Menu } from "./Menu.js";
6
+ import { DropdownMenu } from "./DropdownMenu.js";
7
+ import { Checkbox } from "./Checkbox.js";
8
+ import { StatusPill, statusTone } from "./StatusPill.js";
9
+ import { Field, TextField, Textarea, Select, RadioGroup, Switch } from "./forms.js";
10
+ import { Combobox, defaultFilter } from "./Combobox.js";
11
+ import { DatePicker, DateRangePicker, Calendar, formatDate, parseDate } from "./DatePicker.js";
12
+ import { Alert, Toaster, toast, Tooltip } from "./feedback.js";
13
+ import { Dialog, Drawer } from "./Dialog.js";
14
+ import { DataTable } from "./DataTable.js";
15
+ import { Card, Tabs, SideNav, Breadcrumb, Avatar } from "./layout.js";
16
+ import { Stack, Grid, Container, AppShell, useBreakpoint, useResponsive, breakpoints } from "./layout2.js";
17
+ import { Surface } from "./Surface.js";
18
+ import { AuraProvider, useAuraLocale, STRINGS } from "./locale.js";
19
+ import { Stat } from "./Stat.js";
20
+ import { TimePicker, parseTime } from "./TimePicker.js";
21
+ import { FileUpload, formatBytes } from "./FileUpload.js";
22
+ import { createTheme, contrast, scale } from "./theme.js";
23
+ import { ThemeStyle } from "./ThemeStyle.js";
24
+ import { Badge, Tag, Progress, Skeleton, EmptyState, Pagination, Accordion, Popover } from "./extra.js";
25
+ export {
26
+ Accordion,
27
+ Alert,
28
+ AppShell,
29
+ AuraProvider,
30
+ Avatar,
31
+ Badge,
32
+ Breadcrumb,
33
+ Button,
34
+ Calendar,
35
+ Card,
36
+ Checkbox,
37
+ Combobox,
38
+ Container,
39
+ DataTable,
40
+ DatePicker,
41
+ DateRangePicker,
42
+ Dialog,
43
+ Drawer,
44
+ DropdownMenu,
45
+ EmptyState,
46
+ Field,
47
+ FileUpload,
48
+ Grid,
49
+ ICONS,
50
+ Icon,
51
+ IconButton,
52
+ Menu,
53
+ Pagination,
54
+ Popover,
55
+ Progress,
56
+ RadioGroup,
57
+ STRINGS,
58
+ Select,
59
+ SideNav,
60
+ Skeleton,
61
+ Stack,
62
+ Stat,
63
+ StatusPill,
64
+ Surface,
65
+ Switch,
66
+ Tabs,
67
+ Tag,
68
+ TextField,
69
+ Textarea,
70
+ ThemeStyle,
71
+ TimePicker,
72
+ Toaster,
73
+ Tooltip,
74
+ scale as brandScale,
75
+ breakpoints,
76
+ defaultFilter as comboboxFilter,
77
+ contrast,
78
+ createTheme,
79
+ formatBytes,
80
+ formatDate,
81
+ iconNames,
82
+ parseDate,
83
+ parseTime,
84
+ statusTone,
85
+ toast,
86
+ useAuraLocale,
87
+ useBreakpoint,
88
+ useResponsive
89
+ };
@@ -0,0 +1,84 @@
1
+ 'use client';
2
+ import * as React from "react";
3
+ const h = React.createElement;
4
+ function cx() {
5
+ return Array.prototype.filter.call(arguments, Boolean).join(" ");
6
+ }
7
+ function omit(src, keys) {
8
+ var out = {};
9
+ for (var k in src) if (Object.prototype.hasOwnProperty.call(src, k) && keys.indexOf(k) < 0) out[k] = src[k];
10
+ return out;
11
+ }
12
+ function useMaybeControlled(value, initial, onChange) {
13
+ var s = React.useState(initial);
14
+ var controlled = value !== void 0;
15
+ return [controlled ? value : s[0], function(next) {
16
+ if (!controlled) s[1](next);
17
+ if (onChange) onChange(next);
18
+ }];
19
+ }
20
+ var collator = typeof Intl !== "undefined" ? new Intl.Collator(["th", "en"], { numeric: true, sensitivity: "base" }) : null;
21
+ function compare(a, b) {
22
+ if (a == null && b == null) return 0;
23
+ if (a == null) return 1;
24
+ if (b == null) return -1;
25
+ if (typeof a === "number" && typeof b === "number") return a - b;
26
+ return collator ? collator.compare(String(a), String(b)) : String(a).localeCompare(String(b));
27
+ }
28
+ const uid = React.useId || function() {
29
+ const r = React.useRef(null);
30
+ if (!r.current) r.current = "aura-" + Math.random().toString(36).slice(2, 9);
31
+ return r.current;
32
+ };
33
+ var FOCUSABLE = 'a[href],button:not([disabled]),input:not([disabled]),select:not([disabled]),textarea:not([disabled]),[tabindex]:not([tabindex="-1"])';
34
+ function noopSubscribe() {
35
+ return function() {
36
+ };
37
+ }
38
+ function yes() {
39
+ return true;
40
+ }
41
+ function no() {
42
+ return false;
43
+ }
44
+ function useMounted() {
45
+ return React.useSyncExternalStore(noopSubscribe, yes, no);
46
+ }
47
+ var useIsoLayoutEffect = typeof window !== "undefined" ? React.useLayoutEffect : React.useEffect;
48
+ function trapTab(e, container) {
49
+ if (e.key !== "Tab" || !container) return;
50
+ var list = Array.prototype.filter.call(container.querySelectorAll(FOCUSABLE), function(el) {
51
+ return el.tabIndex >= 0 && el.offsetParent !== null;
52
+ });
53
+ if (!list.length) return;
54
+ var first = list[0], last = list[list.length - 1];
55
+ if (e.shiftKey && document.activeElement === first) {
56
+ e.preventDefault();
57
+ last.focus();
58
+ } else if (!e.shiftKey && document.activeElement === last) {
59
+ e.preventDefault();
60
+ first.focus();
61
+ }
62
+ }
63
+ function useMergedRef(a, b) {
64
+ return React.useCallback(function(node) {
65
+ [a, b].forEach(function(r) {
66
+ if (!r) return;
67
+ if (typeof r === "function") r(node);
68
+ else r.current = node;
69
+ });
70
+ }, [a, b]);
71
+ }
72
+ export {
73
+ FOCUSABLE,
74
+ collator,
75
+ compare,
76
+ cx,
77
+ omit,
78
+ trapTab,
79
+ uid,
80
+ useIsoLayoutEffect,
81
+ useMaybeControlled,
82
+ useMergedRef,
83
+ useMounted
84
+ };