klun-ui 0.2.0 → 0.3.0

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.
package/CHANGELOG.md CHANGED
@@ -5,6 +5,163 @@ All notable changes to **klun-ui** are documented here. The format follows
5
5
  [Semantic Versioning](https://semver.org/) (pre-1.0: minor/patch bumps may carry
6
6
  small breaking changes).
7
7
 
8
+ ## [0.3.0] — 2026-09-16
9
+
10
+ ### Added
11
+ - **Settings is now a full five-tab page** (`MetronicSettingsTemplate`), each tab
12
+ interactive and exportable on its own:
13
+ - **Profile** (`ProfileSection`) — photo upload with a local preview,
14
+ personal information with validation and dirty tracking, regional
15
+ preferences (language / timezone / date format / week start).
16
+ - **Account** (`AccountSection`) — password change with a live strength meter
17
+ and requirement checklist, two-factor enrolment (setup key + copy button +
18
+ `DigitInput` verification, recovery codes), active-session list with revoke
19
+ and “sign out others”, and a danger zone (deactivate + delete behind typed
20
+ confirmation).
21
+ - **Notifications** (`NotificationsSection`) — channel matrix (email / push /
22
+ SMS × event) with column-level select-all and indeterminate state, digest
23
+ cadence, quiet hours and a test send.
24
+ - **Billing** (`BillingSection`) — current plan with usage meters, plan
25
+ switching, payment methods (add / make default / remove), billing details and
26
+ an invoice history table.
27
+ - **API keys** (`ApiKeysSection`) — usage summary, create dialog with scope
28
+ picker, one-time secret reveal, rotate and revoke.
29
+ - Exports: `ProfileSection`, `AccountSection`, `NotificationsSection`,
30
+ `BillingSection`, `ApiKeysSection`, `SETTINGS_NAV` and `SettingsSectionKey`
31
+ join the templates subpath.
32
+ - Storybook: one story per settings tab under *Templates / Metronic*.
33
+ - **Interactive demo shell** (`MetronicDashboardTemplate`) — the top bar is now
34
+ fully wired instead of decorative:
35
+ - a **⌘K / Ctrl-K command palette** (navigate + actions + recents), also
36
+ opened from the search box and the help menu;
37
+ - a **notification centre** with unread indicator, per-item read state and
38
+ “mark all as read”;
39
+ - an **appearance menu** that live-switches `data-theme` (light / dark),
40
+ `data-density` (comfortable / compact) and `data-mode` (metronic / blue /
41
+ purple / orange / green / slate) across the whole demo;
42
+ - an **account menu** (profile, billing, team & roles, sign out) and a working
43
+ “New order” shortcut that jumps to the orders page and opens its dialog.
44
+ - **Orders is a full CRUD page** — create / edit in a modal with validation,
45
+ a details drawer with a status timeline, advance-status, refund, duplicate and
46
+ “email receipt” actions, delete behind `Confirm`, working bulk actions
47
+ (mark fulfilled / refund) and a search empty state.
48
+ - `DashboardScreen` accepts `onViewAllOrders` — “View all” and recent-order rows
49
+ now jump to the orders page.
50
+ - **Four more back-office screens** (Metronic examples):
51
+ - **`DepartmentsScreen`** — organisation tree on the Table’s tree mode:
52
+ expandable departments with manager, headcount and budget usage, full CRUD
53
+ (deleting a parent reparents its children) and a details drawer that links to
54
+ the team page.
55
+ - **`RoleTreeScreen`** — role hierarchy built on the `Tree` component: two
56
+ panes showing the selected role’s ancestors, the permissions it *owns*
57
+ versus the ones it *inherits*, its members, and a child-role comparison
58
+ table with clone / delete actions.
59
+ - **`TasksScreen`** — cron-style scheduled tasks: human-readable schedule,
60
+ last / next run, inline enable switch, “run now” with a simulated execution,
61
+ a run-history drawer and a create/edit dialog with schedule presets,
62
+ timezone, retries and notify-on-failure.
63
+ - **`AuditScreen`** — audit trail with search, action / severity / range
64
+ filters, severity and result badges, and a drawer exposing the request
65
+ metadata JSON (copyable) plus actor actions.
66
+ - **User management is now a full module** — the members list gained a security
67
+ summary (2FA coverage, flags, pending invites), department / role / status /
68
+ security filters, row selection with bulk actions (activate, suspend, reset
69
+ 2FA, assign role, move department) and a **user detail drawer** with four
70
+ tabs: profile, access (roles plus direct allow/deny overrides and the
71
+ resulting effective permission set), security (account state, 2FA, password
72
+ policy, per-device sessions) and activity (that member’s audit trail, with a
73
+ jump into the audit screen filtered by them).
74
+ - **`DepartmentFilter`** — a cascading department picker built on `Dropdown`:
75
+ branches expand in place (the chevron only toggles, the row selects), every
76
+ row shows the member count of its whole branch, and choosing a parent filters
77
+ the list by that department *and* its sub-departments.
78
+ - **Demo i18n** (`i18n.tsx`) — the shell now renders inside `ConfigProvider`, so
79
+ every component string follows the active locale pack (pagination, filters,
80
+ export, modal buttons, …), while nav labels, page headers and shell copy come
81
+ from a demo dictionary covering en-US, zh-CN, zh-TW and ja-JP. A language menu
82
+ in the top bar switches between all 17 shipped locales and flips the layout to
83
+ RTL (Arabic).
84
+ - `PageHeader`, `useDemoText`, `demoTextFor`, `DEMO_TEXT`, `LOCALE_OPTIONS` and
85
+ `RTL_LOCALES` join the templates subpath.
86
+ - **`Cascader` gained the props it was missing for real-world filters** —
87
+ `clearable` (an inline `×`), `renderOption` (decorate panel rows without
88
+ touching the trigger label) and `defaultValue` (uncontrolled usage). The panel
89
+ is now `role="menu"` with `role="menuitem"` / `aria-selected` rows, and the
90
+ component ships 9 unit tests.
91
+
92
+ ### Changed
93
+ - **The settings page is full width by default** — it now fills the host content
94
+ area instead of being capped at 1000px. Pass `maxWidth={1000}` (or any CSS
95
+ length) to restore a centred column.
96
+ - `MetronicSettingsTemplate` accepts `section` / `defaultSection` /
97
+ `onSectionChange` so the active tab can be controlled from the router.
98
+ - The page header shows a dirty-state badge that flips between
99
+ “All changes saved” and “Unsaved changes”.
100
+ - `MetronicTopBar` now takes props (appearance state, notifications and action
101
+ handlers) instead of rendering static buttons; `OrdersScreen` takes an optional
102
+ `createRequest` counter used by the shell’s “New order” button.
103
+ - `MetronicSidebar` items take an optional `label` (resolved from the demo
104
+ dictionary), support multiple nested groups and hairline section breaks, and
105
+ the top bar gained `localeCode` / `onLocaleChange`.
106
+ - `UsersScreen` accepts `initialDepartment` / `onOpenAudit` / `onOpenRoles` /
107
+ `onOpenDepartments` so the departments and audit screens can drill straight
108
+ into it, and `AuditScreen` accepts `initialActor` for the reverse jump.
109
+ - The department filter in the demo is now the design-system **`Cascader`**
110
+ (multi-column drill-down with per-row member counts) instead of a hand-rolled
111
+ dropdown, and `Cascader` follows the density tokens — heights and padding come
112
+ from `--klun-control-h-*` / `--klun-field-px-*`, so compact density shrinks it
113
+ like every other field.
114
+
115
+ ## [0.2.2] — 2026-09-16
116
+
117
+ ### Added
118
+ - **Back-office business pages (Metronic examples, continued).** The templates
119
+ subpath now ships a complete admin set beside the dashboard & settings
120
+ examples — every screen is exported for standalone use and previewable in
121
+ Storybook under *Templates / Metronic*:
122
+ - **RBAC** — `RolesScreen` (role list + module × action permission matrix
123
+ with per-row select-all, dirty tracking and Reset/Save) and `UsersScreen`
124
+ (team list with role / status / 2FA, invite & edit in a modal, suspend and
125
+ remove behind the confirm dialog).
126
+ - **CRUD with two editor flows** — `ProductsScreen` (list + detail drawer +
127
+ delete confirm) supports quick add/edit in a **modal** and a route-style
128
+ **full-page wizard** (`ProductWizardPage`: basics → pricing & stock →
129
+ review, with per-step validation). With a router, mount the wizard at
130
+ `/products/new` and `/products/:id/edit`.
131
+ - `OrdersScreen` (selection + bulk actions, column filters, CSV export,
132
+ pagination), `CustomersScreen` (segments, lifetime spend, relative times)
133
+ and `ReportsScreen` (sales / traffic views with an area chart, donut and
134
+ breakdown tables).
135
+ - **Table toolbar & pager are now density-aware**, and the remaining controls
136
+ joined the density axis: command-menu items, select-menu options,
137
+ horizontal-filter pills, popconfirm buttons, bulk-action bar, tree rows and
138
+ the image-viewer controls all follow `data-density`.
139
+
140
+ ### Changed
141
+ - **The Metronic example pages are compact by default** (`data-density="compact"`
142
+ on the template roots) — buttons 40→36, 36→32, tiny 28→24, fields 40→36,
143
+ table toolbar / pager 32→28. Drop the attribute to get the comfortable scale
144
+ back.
145
+ - Table toolbar buttons now use the small tier in the default scale as well
146
+ (36 → 32), matching the pager.
147
+
148
+ ## [0.2.1] — 2026-09-16
149
+
150
+ ### Added
151
+ - **Metronic example pages — `MetronicDashboardTemplate` /
152
+ `MetronicSettingsTemplate`** (templates subpath). They port the Metronic
153
+ design-system examples onto klun-ui components inside the Metronic 9.0 skin
154
+ (`data-mode="metronic"`, drop the attribute to fall back to the default
155
+ theme):
156
+ - *Dashboard* — app shell (brand sidebar with badge + nested nav, search top
157
+ bar) around KPI tiles with inline sparklines, a revenue/orders bar chart
158
+ with pill tabs, a traffic-sources donut and a recent-orders table.
159
+ - *Settings* — breadcrumb + section nav with profile photo, personal
160
+ information form (inputs, selects, textarea), and notification toggles.
161
+ - The charts (`Sparkline` / `BarChart` / `DonutChart`) are dependency-free
162
+ inline SVG and fully token-driven, so both pages follow the skin and dark
163
+ mode automatically. Preview both in Storybook under *Templates / Metronic*.
164
+
8
165
  ## [0.2.0] — 2026-09-16
9
166
 
10
167
  ### Added
package/README.md CHANGED
@@ -100,11 +100,11 @@ All components and their prop types are named exports; the `cx` classnames helpe
100
100
 
101
101
  ## Templates
102
102
 
103
- Full-screen example compositions are available from the `klun-ui/templates` subpath — copy-and-go starting points built entirely from klun-ui components (`DashboardTemplate`, `AIAssistantTemplate`, `AgentChatTemplate`, `CryptoTemplate`, `MarketingTemplate`, `CalendarTemplate`, `PricingTemplate`, `SettingsTemplate`):
103
+ Full-screen example compositions are available from the `klun-ui/templates` subpath — copy-and-go starting points built entirely from klun-ui components (`DashboardTemplate`, `AIAssistantTemplate`, `AgentChatTemplate`, `CryptoTemplate`, `MarketingTemplate`, `CalendarTemplate`, `PricingTemplate`, `SettingsTemplate`, plus the Metronic examples — `MetronicDashboardTemplate` / `MetronicSettingsTemplate` (five interactive tabs: profile, account security, notifications, billing, API keys — also exported individually as `ProfileSection`, `AccountSection`, `NotificationsSection`, `BillingSection`, `ApiKeysSection`) and the back-office screens `OrdersScreen`, `ProductsScreen` (CRUD with modal + full-page wizard editors), `CustomersScreen`, `UsersScreen`, `RolesScreen` (RBAC), `ReportsScreen` — which render inside the Metronic 9.0 skin at compact density):
104
104
 
105
105
  ```tsx
106
106
  import "klun-ui/styles.css";
107
- import { DashboardTemplate, AIAssistantTemplate, AgentChatTemplate, CryptoTemplate, MarketingTemplate, CalendarTemplate, PricingTemplate, SettingsTemplate } from "klun-ui/templates";
107
+ import { DashboardTemplate, AIAssistantTemplate, AgentChatTemplate, CryptoTemplate, MarketingTemplate, CalendarTemplate, PricingTemplate, SettingsTemplate, MetronicDashboardTemplate, MetronicSettingsTemplate } from "klun-ui/templates";
108
108
 
109
109
  export default function App() {
110
110
  return <DashboardTemplate />;
@@ -0,0 +1,18 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ type ChipColor = "gray" | "blue" | "orange" | "red" | "green" | "purple" | "yellow" | "teal" | "sky" | "pink";
5
+ interface ChipProps extends HTMLAttributes<HTMLSpanElement> {
6
+ color?: ChipColor;
7
+ selected?: boolean;
8
+ /** Show a leading color dot. */
9
+ dot?: boolean;
10
+ /** Show a dismiss (×) button; receives the click handler. */
11
+ onDismiss?: () => void;
12
+ disabled?: boolean;
13
+ children?: ReactNode;
14
+ }
15
+ /** Klun UI Chip — compact, optionally-selectable color category pill. */
16
+ declare const Chip: react.ForwardRefExoticComponent<ChipProps & react.RefAttributes<HTMLSpanElement>>;
17
+
18
+ export { type ChipColor as C, Chip as a, type ChipProps as b };
@@ -0,0 +1,18 @@
1
+ import * as react from 'react';
2
+ import { HTMLAttributes, ReactNode } from 'react';
3
+
4
+ type ChipColor = "gray" | "blue" | "orange" | "red" | "green" | "purple" | "yellow" | "teal" | "sky" | "pink";
5
+ interface ChipProps extends HTMLAttributes<HTMLSpanElement> {
6
+ color?: ChipColor;
7
+ selected?: boolean;
8
+ /** Show a leading color dot. */
9
+ dot?: boolean;
10
+ /** Show a dismiss (×) button; receives the click handler. */
11
+ onDismiss?: () => void;
12
+ disabled?: boolean;
13
+ children?: ReactNode;
14
+ }
15
+ /** Klun UI Chip — compact, optionally-selectable color category pill. */
16
+ declare const Chip: react.ForwardRefExoticComponent<ChipProps & react.RefAttributes<HTMLSpanElement>>;
17
+
18
+ export { type ChipColor as C, Chip as a, type ChipProps as b };
@@ -6539,25 +6539,30 @@ var AutoComplete = forwardRef(
6539
6539
  AutoComplete.displayName = "AutoComplete";
6540
6540
  var Cascader = forwardRef(function Cascader2({
6541
6541
  options = [],
6542
- value = [],
6542
+ value,
6543
+ defaultValue,
6543
6544
  onChange,
6544
6545
  placeholder: placeholderProp,
6545
6546
  size: sizeProp,
6546
6547
  disabled = false,
6547
6548
  separator = " / ",
6548
6549
  changeOnSelect = false,
6550
+ clearable = false,
6551
+ renderOption,
6549
6552
  error = false,
6550
6553
  className,
6551
6554
  ...props
6552
6555
  }, ref) {
6553
6556
  const size = useSize(sizeProp);
6554
- const { cascader } = useLocale();
6557
+ const { cascader, input: inputText } = useLocale();
6555
6558
  const placeholder = placeholderProp ?? cascader.placeholder;
6559
+ const [inner, setInner] = useState(defaultValue ?? []);
6560
+ const current = value ?? inner;
6556
6561
  const [open, setOpen] = useState(false);
6557
- const [active, setActive] = useState(value);
6562
+ const [active, setActive] = useState(current);
6558
6563
  const rootRef = useRef(null);
6559
6564
  useEffect(() => {
6560
- setActive(value);
6565
+ setActive(current);
6561
6566
  }, [open]);
6562
6567
  useEffect(() => {
6563
6568
  if (!open) return;
@@ -6586,7 +6591,7 @@ var Cascader = forwardRef(function Cascader2({
6586
6591
  }
6587
6592
  const labelPath = [];
6588
6593
  let lvl = options;
6589
- for (const key of value) {
6594
+ for (const key of current) {
6590
6595
  const found = (lvl || []).find((o) => o.value === key);
6591
6596
  if (!found) break;
6592
6597
  labelPath.push(found.label);
@@ -6598,10 +6603,16 @@ var Cascader = forwardRef(function Cascader2({
6598
6603
  setActive(nextPath);
6599
6604
  const leaf = !opt.children || !opt.children.length;
6600
6605
  if (leaf || changeOnSelect) {
6606
+ if (value === void 0) setInner(nextPath);
6601
6607
  onChange && onChange(nextPath);
6602
6608
  if (leaf) setOpen(false);
6603
6609
  }
6604
6610
  };
6611
+ const clear = () => {
6612
+ if (value === void 0) setInner([]);
6613
+ setActive([]);
6614
+ onChange && onChange([]);
6615
+ };
6605
6616
  const setRefs = (node) => {
6606
6617
  rootRef.current = node;
6607
6618
  if (typeof ref === "function") ref(node);
@@ -6631,6 +6642,20 @@ var Cascader = forwardRef(function Cascader2({
6631
6642
  i > 0 ? /* @__PURE__ */ jsx("span", { className: "klun-cascader__separator", children: separator }) : null,
6632
6643
  lbl
6633
6644
  ] }, i)) : placeholder }),
6645
+ clearable && labelPath.length && !disabled ? /* @__PURE__ */ jsx(
6646
+ "span",
6647
+ {
6648
+ role: "button",
6649
+ tabIndex: -1,
6650
+ "aria-label": inputText.clear,
6651
+ className: "klun-cascader__clear",
6652
+ onClick: (e) => {
6653
+ e.stopPropagation();
6654
+ clear();
6655
+ },
6656
+ children: /* @__PURE__ */ jsx("i", { className: "ri-close-circle-fill" })
6657
+ }
6658
+ ) : null,
6634
6659
  /* @__PURE__ */ jsx(
6635
6660
  "svg",
6636
6661
  {
@@ -6655,7 +6680,7 @@ var Cascader = forwardRef(function Cascader2({
6655
6680
  ]
6656
6681
  }
6657
6682
  ),
6658
- open ? /* @__PURE__ */ jsx("div", { className: "klun-cascader__panel", children: columns.map((col, ci) => /* @__PURE__ */ jsx(
6683
+ open ? /* @__PURE__ */ jsx("div", { className: "klun-cascader__panel", role: "menu", children: columns.map((col, ci) => /* @__PURE__ */ jsx(
6659
6684
  "div",
6660
6685
  {
6661
6686
  className: cx(
@@ -6669,12 +6694,14 @@ var Cascader = forwardRef(function Cascader2({
6669
6694
  "button",
6670
6695
  {
6671
6696
  type: "button",
6697
+ role: "menuitem",
6672
6698
  className: "klun-cascader__option",
6673
6699
  disabled: opt.disabled,
6674
6700
  onClick: () => pick(ci, opt),
6701
+ "aria-selected": selected,
6675
6702
  "data-selected": selected || void 0,
6676
6703
  children: [
6677
- /* @__PURE__ */ jsx("span", { className: "klun-cascader__option-label", children: opt.label }),
6704
+ /* @__PURE__ */ jsx("span", { className: "klun-cascader__option-label", children: renderOption ? renderOption(opt, ci) : opt.label }),
6678
6705
  hasChildren2 ? /* @__PURE__ */ jsx("i", { className: "ri-arrow-right-s-line klun-cascader__option-arrow" }) : selected ? /* @__PURE__ */ jsx("i", { className: "ri-check-line klun-cascader__option-check" }) : null
6679
6706
  ]
6680
6707
  },
@@ -11601,5 +11628,5 @@ var Popconfirm = forwardRef(function Popconfirm2({
11601
11628
  Popconfirm.displayName = "Popconfirm";
11602
11629
 
11603
11630
  export { Accordion, Alert, AutoComplete, Avatar, AvatarGroup, Badge, Banner, Breadcrumb, BulkAction, BulkActionBar, Button, ButtonGroup, Card, Carousel, Cascader, CharacterCounter, ChartLegend, ChartTooltip, Checkbox, CheckboxCard, CheckboxGroup, Chip, CircularProgress, CodeViewer, Col, Collapse, ColorDot, ColorPicker, ColorSlider, CommandMenu, CompactSelect, CompactSelectForInput, ConfigProvider, Confirm, ContentLabel, ContextMenu2 as ContextMenu, CopyButton, CounterInput, CrossRefBadge, DatePicker, DateRangePicker, DateTimePicker, Descriptions, DiffViewer, DigitInput, Divider, Drawer, Dropdown, EmptyState, ExpiryCountdown, FileUpload, Flex, Form, FormItem, FormList, Format, GaugeBar, Grid, Hint, HorizontalFilter, ImageUpload, ImageViewer, InlineInput, InlineSelect, Input, Kbd, KeyIcon, Label, Layout, LayoutContent, LayoutFooter, LayoutHeader, LayoutSider, List, ListItem, LiveDot, LogViewer, Markdown, Masonry, Menu, Message, Modal, Money, Notification, PageHeader, Pagination, PasswordStrength, Popconfirm, Popover, ProgressBar, Radio, RadioCard, RangeSlider, Rating, RelativeTime, Result, RichEditorToolbar, Row, SegmentedControl, SegmentedProgress, Select, SelectMenu, Skeleton, Slider, Space, Spinner2 as Spinner, Splitter2 as Splitter, SplitterPanel, StatCard, Statistic, StatusBadge, StatusDot, StepIndicator, Switch, Table, Tabs, Tag, Textarea, TimePicker, Timeline, Toast, Toaster, Tooltip, Tree, Wizard, arSA, deDE, enUS, esES, fmt, frFR, idID, itIT, jaJP, koKR, locales, nlNL, parsePatch, plPL, primaryColorVars, ptBR, renderMarkdown, ruRU, toast, trTR, useBreakpoint, useConfig, useContextMenu, useForm, useLocale, useMappedSize, useMessage, useNotification, useSize, viVN, zhCN, zhTW };
11604
- //# sourceMappingURL=chunk-UJOMGMCV.js.map
11605
- //# sourceMappingURL=chunk-UJOMGMCV.js.map
11631
+ //# sourceMappingURL=chunk-I4OHTBZQ.js.map
11632
+ //# sourceMappingURL=chunk-I4OHTBZQ.js.map