@nice2dev/admin 0.1.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 ADDED
@@ -0,0 +1,18 @@
1
+ # Changelog
2
+
3
+ All notable changes to **@nice2dev/admin** will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.1.0] — 2025-06-01
9
+
10
+ ### Added
11
+ - `NiceAdminDashboard` — admin dashboard with configurable widget grid
12
+ - `NiceAdminUsers` — user management table with CRUD and role assignment
13
+ - `NiceAdminRoles` — role management with permission matrix
14
+ - `NiceAdminAuditLog` — audit log viewer with search and filtering
15
+ - `NiceAdminSettings` — system settings editor with sections and validation
16
+ - `NiceAdminNotifications` — notification management panel
17
+ - `NiceFeatureFlags` — feature flag management with environments
18
+ - `NiceImportExport` — data import/export with format selection and mapping
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 NiceToDev
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # @nice2dev/admin
2
+
3
+ Administration panel components for React applications — dashboard, user management, roles, audit log, settings, feature flags, and data import/export.
4
+
5
+ [![npm](https://img.shields.io/npm/v/@nice2dev/admin)](https://www.npmjs.com/package/@nice2dev/admin)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE)
7
+ [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
8
+
9
+ ---
10
+
11
+ ## Installation
12
+
13
+ ```bash
14
+ npm install @nice2dev/admin
15
+ ```
16
+
17
+ **Peer dependencies:** `react >= 17.0.0`, `react-dom >= 17.0.0`
18
+
19
+ ## Components
20
+
21
+ | Component | Description |
22
+ |---|---|
23
+ | `NiceAdminDashboard` | Admin dashboard with configurable widget grid |
24
+ | `NiceAdminUsers` | User management table with CRUD and role assignment |
25
+ | `NiceAdminRoles` | Role management with permission matrix |
26
+ | `NiceAdminAuditLog` | Audit log viewer with search and filtering |
27
+ | `NiceAdminSettings` | System settings editor with sections |
28
+ | `NiceAdminNotifications` | Notification management panel |
29
+ | `NiceFeatureFlags` | Feature flag management with environments |
30
+ | `NiceImportExport` | Data import/export with format selection and mapping |
31
+
32
+ ## Usage
33
+
34
+ ```tsx
35
+ import { NiceAdminDashboard, NiceAdminUsers, NiceFeatureFlags } from '@nice2dev/admin';
36
+
37
+ function AdminPage() {
38
+ return (
39
+ <>
40
+ <NiceAdminDashboard
41
+ widgets={[
42
+ { id: 'users', title: 'Active Users', type: 'stat', value: 1250 },
43
+ { id: 'events', title: 'Events Today', type: 'stat', value: 42 },
44
+ ]}
45
+ />
46
+ <NiceAdminUsers
47
+ onSave={(user) => api.updateUser(user)}
48
+ onDelete={(id) => api.deleteUser(id)}
49
+ />
50
+ <NiceFeatureFlags
51
+ onToggle={(flag, env) => api.toggleFlag(flag, env)}
52
+ />
53
+ </>
54
+ );
55
+ }
56
+ ```
57
+
58
+ ## Types
59
+
60
+ Key TypeScript types exported: `AdminWidget`, `AdminUser`, `AdminRole`, `PermissionAction`, `PermissionResource`, `AuditLogEntry`, `SettingItem`, `FeatureFlag`, `ImportExportJob`, `ColumnMapping`.
61
+
62
+ ## License
63
+
64
+ MIT © NiceToDev
package/dist/index.cjs ADDED
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const e=require("react/jsx-runtime"),a=require("react"),D=a.forwardRef(function(C,y){const{widgets:u,columns:g=4,title:p="Dashboard",headerActions:j,onWidgetClick:h,className:N,style:v}=C;return e.jsxs("div",{ref:y,className:`nice-admin-dashboard ${N??""}`,style:v,children:[e.jsxs("div",{className:"nice-admin-dashboard__header",children:[e.jsx("h2",{children:p}),j&&e.jsx("div",{className:"nice-admin-dashboard__actions",children:j})]}),e.jsx("div",{className:"nice-admin-dashboard__grid",style:{display:"grid",gridTemplateColumns:`repeat(${g}, 1fr)`,gap:16},children:u.map(l=>e.jsxs("div",{className:`nice-admin-dashboard__widget nice-admin-dashboard__widget--${l.type}`,style:{gridColumn:l.colSpan?`span ${l.colSpan}`:void 0,gridRow:l.rowSpan?`span ${l.rowSpan}`:void 0},onClick:()=>h==null?void 0:h(l),role:h?"button":void 0,tabIndex:h?0:void 0,children:[e.jsxs("div",{className:"nice-admin-dashboard__widget-header",children:[l.icon&&e.jsx("span",{className:"nice-admin-dashboard__widget-icon",children:l.icon}),e.jsx("span",{className:"nice-admin-dashboard__widget-title",children:l.title})]}),l.type==="stat"&&e.jsxs("div",{className:"nice-admin-dashboard__stat",children:[e.jsx("span",{className:"nice-admin-dashboard__stat-value",children:l.value}),l.change&&e.jsx("span",{className:`nice-admin-dashboard__stat-change ${l.changePositive?"nice-admin-dashboard__stat-change--positive":"nice-admin-dashboard__stat-change--negative"}`,children:l.change})]}),l.type==="custom"&&l.render&&e.jsx("div",{className:"nice-admin-dashboard__custom",children:l.render()}),(l.type==="chart"||l.type==="table"||l.type==="list")&&l.render&&e.jsx("div",{className:"nice-admin-dashboard__content",children:l.render()})]},l.id))})]})}),I={active:"#22c55e",inactive:"#9ca3af",suspended:"#ef4444",pending:"#eab308"},$=a.forwardRef(function(C,y){const{users:u,availableRoles:g=[],onCreate:p,onEdit:j,onDelete:h,onToggleStatus:N,onChangeRoles:v,searchable:l=!0,title:S="User Management",className:b,style:x}=C,[_,f]=a.useState(""),[i,s]=a.useState(""),n=a.useMemo(()=>{let t=u;if(i&&(t=t.filter(m=>m.status===i)),_.trim()){const m=_.toLowerCase();t=t.filter(A=>A.name.toLowerCase().includes(m)||A.email.toLowerCase().includes(m)||A.roles.some(L=>L.toLowerCase().includes(m)))}return t},[u,i,_]),o=a.useCallback(t=>{if(!N)return;const m=t.status==="active"?"suspended":"active";N(t.id,m)},[N]);return e.jsxs("div",{ref:y,className:`nice-admin-users ${b??""}`,style:x,children:[e.jsxs("div",{className:"nice-admin-users__header",children:[e.jsx("h3",{children:S}),e.jsxs("span",{className:"nice-admin-users__count",children:[u.length," users"]}),p&&e.jsx("button",{className:"nice-admin-users__create-btn",onClick:p,children:"+ Add User"})]}),e.jsxs("div",{className:"nice-admin-users__toolbar",children:[l&&e.jsx("input",{type:"text",value:_,onChange:t=>f(t.target.value),placeholder:"Search users…",className:"nice-admin-users__search"}),e.jsxs("select",{value:i,onChange:t=>s(t.target.value),className:"nice-admin-users__status-filter",children:[e.jsx("option",{value:"",children:"All statuses"}),e.jsx("option",{value:"active",children:"Active"}),e.jsx("option",{value:"inactive",children:"Inactive"}),e.jsx("option",{value:"suspended",children:"Suspended"}),e.jsx("option",{value:"pending",children:"Pending"})]})]}),n.length===0?e.jsx("p",{className:"nice-admin-users__empty",children:"No users found."}):e.jsxs("table",{className:"nice-admin-users__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"User"}),e.jsx("th",{children:"Email"}),e.jsx("th",{children:"Roles"}),e.jsx("th",{children:"Status"}),e.jsx("th",{children:"Created"}),e.jsx("th",{children:"Last Login"}),e.jsx("th",{children:"Actions"})]})}),e.jsx("tbody",{children:n.map(t=>e.jsxs("tr",{children:[e.jsxs("td",{className:"nice-admin-users__user-cell",children:[t.avatarUrl&&e.jsx("img",{src:t.avatarUrl,alt:"",className:"nice-admin-users__avatar"}),e.jsx("span",{children:t.name})]}),e.jsx("td",{children:t.email}),e.jsx("td",{children:v?e.jsx("select",{multiple:!0,value:t.roles,onChange:m=>{const A=Array.from(m.target.selectedOptions,L=>L.value);v(t.id,A)},className:"nice-admin-users__roles-select",children:g.map(m=>e.jsx("option",{value:m,children:m},m))}):t.roles.join(", ")}),e.jsx("td",{children:e.jsx("span",{className:"nice-admin-users__status-badge",style:{backgroundColor:I[t.status]},onClick:()=>o(t),role:N?"button":void 0,children:t.status})}),e.jsx("td",{children:t.createdAt}),e.jsx("td",{children:t.lastLoginAt??"—"}),e.jsxs("td",{className:"nice-admin-users__actions",children:[j&&e.jsx("button",{onClick:()=>j(t),children:"Edit"}),h&&e.jsx("button",{onClick:()=>h(t.id),children:"Delete"})]})]},t.id))})]})]})}),M=a.forwardRef(function(C,y){var d;const{roles:u,actions:g,resources:p,onPermissionChange:j,onCreate:h,onDelete:N,onRename:v,title:l="Role Management",className:S,style:b}=C,[x,_]=a.useState(((d=u[0])==null?void 0:d.id)??null),[f,i]=a.useState(!1),[s,n]=a.useState(""),[o,t]=a.useState(""),m=u.find(r=>r.id===x),A=a.useCallback(()=>{!s.trim()||!h||(h(s.trim(),o.trim()),n(""),t(""),i(!1))},[s,o,h]),L=(r,c,k)=>{var R;return((R=r.permissions[c])==null?void 0:R.includes(k))??!1};return e.jsxs("div",{ref:y,className:`nice-admin-roles ${S??""}`,style:b,children:[e.jsxs("div",{className:"nice-admin-roles__header",children:[e.jsx("h3",{children:l}),h&&e.jsx("button",{onClick:()=>i(!f),children:"+ New Role"})]}),f&&e.jsxs("div",{className:"nice-admin-roles__create-form",children:[e.jsx("input",{type:"text",value:s,onChange:r=>n(r.target.value),placeholder:"Role name"}),e.jsx("input",{type:"text",value:o,onChange:r=>t(r.target.value),placeholder:"Description"}),e.jsx("button",{onClick:A,disabled:!s.trim(),children:"Create"}),e.jsx("button",{onClick:()=>i(!1),children:"Cancel"})]}),e.jsx("div",{className:"nice-admin-roles__tabs",children:u.map(r=>e.jsxs("button",{className:`nice-admin-roles__tab ${r.id===x?"nice-admin-roles__tab--active":""}`,onClick:()=>_(r.id),style:r.color?{borderColor:r.color}:void 0,children:[r.name,r.userCount!=null&&e.jsxs("span",{className:"nice-admin-roles__tab-count",children:["(",r.userCount,")"]}),r.isSystem&&e.jsx("span",{className:"nice-admin-roles__tab-system",children:"🔒"})]},r.id))}),m&&e.jsxs("div",{className:"nice-admin-roles__matrix-wrap",children:[m.description&&e.jsx("p",{className:"nice-admin-roles__description",children:m.description}),e.jsxs("table",{className:"nice-admin-roles__matrix",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Resource"}),g.map(r=>e.jsx("th",{title:r.description,children:r.label},r.id))]})}),e.jsx("tbody",{children:p.map(r=>e.jsxs("tr",{children:[e.jsx("td",{children:r.label}),g.map(c=>{const k=L(m,r.id,c.id);return e.jsx("td",{children:e.jsx("input",{type:"checkbox",checked:k,onChange:()=>j==null?void 0:j(m.id,r.id,c.id,!k),disabled:m.isSystem})},c.id)})]},r.id))})]}),!m.isSystem&&e.jsxs("div",{className:"nice-admin-roles__role-actions",children:[v&&e.jsx("button",{onClick:()=>{const r=prompt("New role name:",m.name);r&&v(m.id,r)},children:"Rename"}),N&&e.jsx("button",{onClick:()=>N(m.id),children:"Delete Role"})]})]})]})}),T={info:{color:"#3b82f6",label:"INFO"},warning:{color:"#eab308",label:"WARN"},error:{color:"#ef4444",label:"ERROR"},critical:{color:"#dc2626",label:"CRIT"}},U=a.forwardRef(function(C,y){const{entries:u,onEntryClick:g,onLoadMore:p,hasMore:j=!1,searchable:h=!0,showSeverityFilter:N=!0,title:v="Audit Log",className:l,style:S}=C,[b,x]=a.useState(""),[_,f]=a.useState(""),i=a.useMemo(()=>{let s=u;if(_&&(s=s.filter(n=>n.severity===_)),b.trim()){const n=b.toLowerCase();s=s.filter(o=>{var t;return o.actorName.toLowerCase().includes(n)||o.action.toLowerCase().includes(n)||o.resource.toLowerCase().includes(n)||((t=o.details)==null?void 0:t.toLowerCase().includes(n))})}return s},[u,_,b]);return e.jsxs("div",{ref:y,className:`nice-admin-audit-log ${l??""}`,style:S,children:[e.jsxs("div",{className:"nice-admin-audit-log__header",children:[e.jsx("h3",{children:v}),e.jsxs("span",{className:"nice-admin-audit-log__count",children:[u.length," entries"]})]}),e.jsxs("div",{className:"nice-admin-audit-log__toolbar",children:[h&&e.jsx("input",{type:"text",value:b,onChange:s=>x(s.target.value),placeholder:"Search audit log…",className:"nice-admin-audit-log__search"}),N&&e.jsxs("select",{value:_,onChange:s=>f(s.target.value),className:"nice-admin-audit-log__severity-filter",children:[e.jsx("option",{value:"",children:"All severities"}),e.jsx("option",{value:"info",children:"Info"}),e.jsx("option",{value:"warning",children:"Warning"}),e.jsx("option",{value:"error",children:"Error"}),e.jsx("option",{value:"critical",children:"Critical"})]})]}),i.length===0?e.jsx("p",{className:"nice-admin-audit-log__empty",children:"No audit log entries found."}):e.jsxs("table",{className:"nice-admin-audit-log__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Timestamp"}),e.jsx("th",{children:"Severity"}),e.jsx("th",{children:"Actor"}),e.jsx("th",{children:"Action"}),e.jsx("th",{children:"Resource"}),e.jsx("th",{children:"IP"}),e.jsx("th",{children:"Details"})]})}),e.jsx("tbody",{children:i.map(s=>{const n=T[s.severity];return e.jsxs("tr",{className:"nice-admin-audit-log__row",onClick:()=>g==null?void 0:g(s),role:g?"button":void 0,tabIndex:g?0:void 0,children:[e.jsx("td",{children:s.timestamp}),e.jsx("td",{children:e.jsx("span",{className:"nice-admin-audit-log__severity",style:{color:n.color},children:n.label})}),e.jsx("td",{children:s.actorName}),e.jsx("td",{children:s.action}),e.jsxs("td",{children:[s.resource,s.resourceId?` #${s.resourceId}`:""]}),e.jsx("td",{children:s.ipAddress??"—"}),e.jsx("td",{className:"nice-admin-audit-log__details",children:s.details??"—"})]},s.id)})})]}),j&&p&&e.jsx("button",{className:"nice-admin-audit-log__load-more",onClick:p,children:"Load more"})]})}),q=a.forwardRef(function(C,y){const{settings:u,onSave:g,onChange:p,onReset:j,saving:h=!1,title:N="Settings",className:v,style:l}=C,[S,b]=a.useState(()=>{const s={};for(const n of u)s[n.key]=n.value;return s}),x=a.useCallback((s,n)=>{b(o=>({...o,[s]:n})),p==null||p(s,n)},[p]),_=a.useCallback(()=>{g==null||g(S)},[g,S]),f=new Map;for(const s of u){const n=s.section??"General";f.has(n)||f.set(n,[]),f.get(n).push(s)}const i=s=>{var o;const n=S[s.key];switch(s.type){case"boolean":return e.jsxs("label",{className:"nice-admin-settings__toggle",children:[e.jsx("input",{type:"checkbox",checked:!!n,onChange:t=>x(s.key,t.target.checked)}),s.label]});case"select":return e.jsx("select",{value:String(n??""),onChange:t=>x(s.key,t.target.value),className:"nice-admin-settings__select",children:(o=s.options)==null?void 0:o.map(t=>e.jsx("option",{value:t.value,children:t.label},t.value))});case"textarea":return e.jsx("textarea",{value:String(n??""),onChange:t=>x(s.key,t.target.value),placeholder:s.placeholder,className:"nice-admin-settings__textarea",rows:4});case"number":return e.jsx("input",{type:"number",value:n!=null?Number(n):"",onChange:t=>x(s.key,parseFloat(t.target.value)||0),placeholder:s.placeholder,className:"nice-admin-settings__input"});case"color":return e.jsx("input",{type:"color",value:String(n??"#000000"),onChange:t=>x(s.key,t.target.value),className:"nice-admin-settings__color"});case"password":return e.jsx("input",{type:"password",value:String(n??""),onChange:t=>x(s.key,t.target.value),placeholder:s.placeholder,className:"nice-admin-settings__input",autoComplete:"new-password"});default:return e.jsx("input",{type:"text",value:String(n??""),onChange:t=>x(s.key,t.target.value),placeholder:s.placeholder,className:"nice-admin-settings__input"})}};return e.jsxs("div",{ref:y,className:`nice-admin-settings ${v??""}`,style:l,children:[e.jsx("div",{className:"nice-admin-settings__header",children:e.jsx("h3",{children:N})}),Array.from(f.entries()).map(([s,n])=>e.jsxs("fieldset",{className:"nice-admin-settings__section",children:[e.jsx("legend",{children:s}),n.map(o=>e.jsxs("div",{className:"nice-admin-settings__field",children:[o.type!=="boolean"&&e.jsxs("label",{className:"nice-admin-settings__label",children:[o.label,o.required&&e.jsx("span",{className:"nice-admin-settings__required",children:"*"})]}),o.description&&e.jsx("p",{className:"nice-admin-settings__description",children:o.description}),i(o)]},o.key))]},s)),e.jsxs("div",{className:"nice-admin-settings__actions",children:[e.jsx("button",{className:"nice-admin-settings__save-btn",onClick:_,disabled:h,children:h?"Saving…":"Save Settings"}),j&&e.jsx("button",{className:"nice-admin-settings__reset-btn",onClick:j,children:"Reset to Defaults"})]})]})}),O=a.forwardRef(function(C,y){const{notifications:u,availableChannels:g=["email","push","sms","in-app","webhook"],onToggle:p,onEdit:j,onTest:h,onCreate:N,onDelete:v,title:l="Notification Management",className:S,style:b}=C,[x,_]=a.useState(""),f=a.useMemo(()=>{if(!x.trim())return u;const i=x.toLowerCase();return u.filter(s=>{var n;return s.name.toLowerCase().includes(i)||s.event.toLowerCase().includes(i)||((n=s.description)==null?void 0:n.toLowerCase().includes(i))})},[u,x]);return e.jsxs("div",{ref:y,className:`nice-admin-notifications ${S??""}`,style:b,children:[e.jsxs("div",{className:"nice-admin-notifications__header",children:[e.jsx("h3",{children:l}),N&&e.jsx("button",{onClick:N,children:"+ New Notification"})]}),e.jsx("input",{type:"text",value:x,onChange:i=>_(i.target.value),placeholder:"Search notifications…",className:"nice-admin-notifications__search"}),f.length===0?e.jsx("p",{className:"nice-admin-notifications__empty",children:"No notifications found."}):e.jsxs("table",{className:"nice-admin-notifications__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Enabled"}),e.jsx("th",{children:"Name"}),e.jsx("th",{children:"Event"}),e.jsx("th",{children:"Channels"}),e.jsx("th",{children:"Last Sent"}),e.jsx("th",{children:"Sent"}),e.jsx("th",{children:"Actions"})]})}),e.jsx("tbody",{children:f.map(i=>e.jsxs("tr",{children:[e.jsx("td",{children:e.jsx("input",{type:"checkbox",checked:i.enabled,onChange:()=>p==null?void 0:p(i.id,!i.enabled)})}),e.jsxs("td",{children:[e.jsx("strong",{children:i.name}),i.description&&e.jsx("br",{}),i.description&&e.jsx("small",{children:i.description})]}),e.jsx("td",{children:e.jsx("code",{children:i.event})}),e.jsx("td",{children:i.channels.join(", ")}),e.jsx("td",{children:i.lastSentAt??"—"}),e.jsx("td",{children:i.sentCount??0}),e.jsxs("td",{className:"nice-admin-notifications__actions",children:[j&&e.jsx("button",{onClick:()=>j(i),children:"Edit"}),h&&e.jsx("button",{onClick:()=>h(i.id),children:"Test"}),v&&e.jsx("button",{onClick:()=>v(i.id),children:"Delete"})]})]},i.id))})]})]})}),P=a.forwardRef(function(C,y){const{flags:u,environmentNames:g=["development","staging","production"],onToggle:p,onPercentageChange:j,onCreate:h,onDelete:N,onEdit:v,title:l="Feature Flags",className:S,style:b}=C,[x,_]=a.useState(""),[f,i]=a.useState(!1),[s,n]=a.useState(""),[o,t]=a.useState(""),[m,A]=a.useState(""),L=a.useMemo(()=>{if(!x.trim())return u;const c=x.toLowerCase();return u.filter(k=>{var R,w;return k.key.toLowerCase().includes(c)||k.name.toLowerCase().includes(c)||((R=k.description)==null?void 0:R.toLowerCase().includes(c))||((w=k.tags)==null?void 0:w.some(F=>F.toLowerCase().includes(c)))})},[u,x]),d=a.useCallback(()=>{!s.trim()||!o.trim()||!h||(h(s.trim(),o.trim(),m.trim()),n(""),t(""),A(""),i(!1))},[s,o,m,h]),r=(c,k)=>c.environments.find(R=>R.name===k);return e.jsxs("div",{ref:y,className:`nice-feature-flags ${S??""}`,style:b,children:[e.jsxs("div",{className:"nice-feature-flags__header",children:[e.jsx("h3",{children:l}),e.jsxs("span",{className:"nice-feature-flags__count",children:[u.length," flags"]}),h&&e.jsx("button",{onClick:()=>i(!f),children:"+ New Flag"})]}),f&&e.jsxs("div",{className:"nice-feature-flags__create-form",children:[e.jsx("input",{type:"text",value:s,onChange:c=>n(c.target.value),placeholder:"flag_key"}),e.jsx("input",{type:"text",value:o,onChange:c=>t(c.target.value),placeholder:"Display name"}),e.jsx("input",{type:"text",value:m,onChange:c=>A(c.target.value),placeholder:"Description"}),e.jsx("button",{onClick:d,disabled:!s.trim()||!o.trim(),children:"Create"}),e.jsx("button",{onClick:()=>i(!1),children:"Cancel"})]}),e.jsx("input",{type:"text",value:x,onChange:c=>_(c.target.value),placeholder:"Search flags…",className:"nice-feature-flags__search"}),L.length===0?e.jsx("p",{className:"nice-feature-flags__empty",children:"No feature flags found."}):e.jsxs("table",{className:"nice-feature-flags__table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Flag"}),g.map(c=>e.jsx("th",{children:c},c)),e.jsx("th",{children:"Tags"}),e.jsx("th",{children:"Updated"}),e.jsx("th",{children:"Actions"})]})}),e.jsx("tbody",{children:L.map(c=>{var k;return e.jsxs("tr",{children:[e.jsx("td",{children:e.jsxs("div",{className:"nice-feature-flags__flag-info",children:[e.jsx("strong",{children:c.name}),e.jsx("code",{className:"nice-feature-flags__key",children:c.key}),c.description&&e.jsx("small",{children:c.description})]})}),g.map(R=>{const w=r(c,R);return e.jsxs("td",{className:"nice-feature-flags__env-cell",children:[e.jsx("input",{type:"checkbox",checked:(w==null?void 0:w.enabled)??!1,onChange:()=>p==null?void 0:p(c.id,R,!((w==null?void 0:w.enabled)??!1))}),(w==null?void 0:w.percentage)!=null&&e.jsx("input",{type:"number",min:0,max:100,value:w.percentage,onChange:F=>j==null?void 0:j(c.id,R,parseInt(F.target.value,10)||0),className:"nice-feature-flags__percentage",title:"Rollout %"})]},R)}),e.jsx("td",{children:((k=c.tags)==null?void 0:k.join(", "))||"—"}),e.jsx("td",{children:c.updatedAt??c.createdAt}),e.jsxs("td",{className:"nice-feature-flags__actions",children:[v&&e.jsx("button",{onClick:()=>v(c),children:"Edit"}),N&&e.jsx("button",{onClick:()=>N(c.id),children:"Delete"})]})]},c.id)})})]})]})}),G=a.forwardRef(function(C,y){var L;const{entities:u,formats:g=["json","csv","xlsx"],jobs:p=[],onImport:j,onExport:h,onDownload:N,title:v="Import / Export",className:l,style:S}=C,[b,x]=a.useState("export"),[_,f]=a.useState(((L=u[0])==null?void 0:L.id)??""),[i,s]=a.useState(g[0]??"json"),[n,o]=a.useState(null),t=a.useCallback(()=>{!j||!n||!_||(j(_,i,n),o(null))},[j,_,i,n]),m=a.useCallback(()=>{!h||!_||h(_,i)},[h,_,i]),A=d=>{var r;o(((r=d.target.files)==null?void 0:r[0])??null)};return e.jsxs("div",{ref:y,className:`nice-import-export ${l??""}`,style:S,children:[e.jsx("div",{className:"nice-import-export__header",children:e.jsx("h3",{children:v})}),e.jsxs("div",{className:"nice-import-export__tabs",children:[e.jsx("button",{className:`nice-import-export__tab ${b==="import"?"nice-import-export__tab--active":""}`,onClick:()=>x("import"),children:"Import"}),e.jsx("button",{className:`nice-import-export__tab ${b==="export"?"nice-import-export__tab--active":""}`,onClick:()=>x("export"),children:"Export"})]}),e.jsxs("div",{className:"nice-import-export__form",children:[e.jsxs("label",{children:["Entity",e.jsx("select",{value:_,onChange:d=>f(d.target.value),children:u.map(d=>e.jsx("option",{value:d.id,children:d.label},d.id))})]}),e.jsxs("label",{children:["Format",e.jsx("select",{value:i,onChange:d=>s(d.target.value),children:g.map(d=>e.jsx("option",{value:d,children:d.toUpperCase()},d))})]}),b==="import"&&e.jsxs(e.Fragment,{children:[e.jsxs("label",{children:["File",e.jsx("input",{type:"file",onChange:A,accept:`.${i}`})]}),e.jsx("button",{className:"nice-import-export__action-btn",onClick:t,disabled:!n,children:"Start Import"})]}),b==="export"&&e.jsx("button",{className:"nice-import-export__action-btn",onClick:m,children:"Start Export"})]}),p.length>0&&e.jsxs("div",{className:"nice-import-export__jobs",children:[e.jsx("h4",{children:"Recent Jobs"}),e.jsxs("table",{className:"nice-import-export__jobs-table",children:[e.jsx("thead",{children:e.jsxs("tr",{children:[e.jsx("th",{children:"Type"}),e.jsx("th",{children:"Format"}),e.jsx("th",{children:"Status"}),e.jsx("th",{children:"Progress"}),e.jsx("th",{children:"Errors"}),e.jsx("th",{children:"Created"}),e.jsx("th",{})]})}),e.jsx("tbody",{children:p.map(d=>e.jsxs("tr",{children:[e.jsx("td",{children:d.type}),e.jsx("td",{children:d.format.toUpperCase()}),e.jsx("td",{children:e.jsx("span",{className:`nice-import-export__status nice-import-export__status--${d.status}`,children:d.status})}),e.jsx("td",{children:d.processedRows!=null&&d.totalRows?`${d.processedRows} / ${d.totalRows}`:"—"}),e.jsx("td",{children:d.errorCount??0}),e.jsx("td",{children:d.createdAt}),e.jsx("td",{children:d.type==="export"&&d.status==="completed"&&N&&e.jsx("button",{onClick:()=>N(d.id),children:"Download"})})]},d.id))})]})]})]})});exports.NiceAdminAuditLog=U;exports.NiceAdminDashboard=D;exports.NiceAdminNotifications=O;exports.NiceAdminRoles=M;exports.NiceAdminSettings=q;exports.NiceAdminUsers=$;exports.NiceFeatureFlags=P;exports.NiceImportExport=G;
@@ -0,0 +1,368 @@
1
+ import { default as default_2 } from 'react';
2
+
3
+ /** Admin notification template. */
4
+ export declare interface AdminNotification {
5
+ id: string;
6
+ name: string;
7
+ description?: string;
8
+ event: string;
9
+ channels: NotificationChannel[];
10
+ enabled: boolean;
11
+ template?: string;
12
+ lastSentAt?: string;
13
+ sentCount?: number;
14
+ }
15
+
16
+ /** Role definition. */
17
+ export declare interface AdminRole {
18
+ id: string;
19
+ name: string;
20
+ description?: string;
21
+ color?: string;
22
+ isSystem?: boolean;
23
+ /** Map of resourceId → actionId[] granted. */
24
+ permissions: Record<string, string[]>;
25
+ userCount?: number;
26
+ }
27
+
28
+ /** Admin user entry. */
29
+ export declare interface AdminUser {
30
+ id: string;
31
+ name: string;
32
+ email: string;
33
+ avatarUrl?: string;
34
+ roles: string[];
35
+ status: 'active' | 'inactive' | 'suspended' | 'pending';
36
+ createdAt: string;
37
+ lastLoginAt?: string;
38
+ }
39
+
40
+ /** Dashboard widget definition. */
41
+ export declare interface AdminWidget {
42
+ id: string;
43
+ title: string;
44
+ type: 'stat' | 'chart' | 'table' | 'list' | 'custom';
45
+ /** Grid column span (1–4). */
46
+ colSpan?: number;
47
+ /** Grid row span. */
48
+ rowSpan?: number;
49
+ /** Widget value for stat type. */
50
+ value?: string | number;
51
+ /** Change indicator (e.g. "+12%"). */
52
+ change?: string;
53
+ /** Whether change is positive. */
54
+ changePositive?: boolean;
55
+ /** Icon/emoji. */
56
+ icon?: string;
57
+ /** Custom render function. */
58
+ render?: () => default_2.ReactNode;
59
+ }
60
+
61
+ /** Audit log entry. */
62
+ export declare interface AuditLogEntry {
63
+ id: string;
64
+ timestamp: string;
65
+ actorName: string;
66
+ actorId?: string;
67
+ action: string;
68
+ resource: string;
69
+ resourceId?: string;
70
+ severity: AuditSeverity;
71
+ details?: string;
72
+ ipAddress?: string;
73
+ metadata?: Record<string, unknown>;
74
+ }
75
+
76
+ /** Audit log severity. */
77
+ export declare type AuditSeverity = 'info' | 'warning' | 'error' | 'critical';
78
+
79
+ /** Column mapping for import. */
80
+ export declare interface ColumnMapping {
81
+ sourceColumn: string;
82
+ targetField: string;
83
+ transform?: string;
84
+ }
85
+
86
+ /** Supported import/export format. */
87
+ export declare type DataFormat = 'json' | 'csv' | 'xlsx' | 'xml' | 'yaml';
88
+
89
+ /** Feature flag definition. */
90
+ export declare interface FeatureFlag {
91
+ id: string;
92
+ key: string;
93
+ name: string;
94
+ description?: string;
95
+ environments: FlagEnvironment[];
96
+ createdAt: string;
97
+ updatedAt?: string;
98
+ tags?: string[];
99
+ }
100
+
101
+ /** Feature flag environment. */
102
+ export declare interface FlagEnvironment {
103
+ name: string;
104
+ enabled: boolean;
105
+ percentage?: number;
106
+ }
107
+
108
+ /** Import/export job status. */
109
+ export declare interface ImportExportJob {
110
+ id: string;
111
+ type: 'import' | 'export';
112
+ format: DataFormat;
113
+ status: 'pending' | 'running' | 'completed' | 'failed';
114
+ fileName?: string;
115
+ totalRows?: number;
116
+ processedRows?: number;
117
+ errorCount?: number;
118
+ createdAt: string;
119
+ completedAt?: string;
120
+ errorMessage?: string;
121
+ }
122
+
123
+ /**
124
+ * {@link NiceAdminAuditLog} — Audit log viewer with search and severity filtering.
125
+ */
126
+ export declare const NiceAdminAuditLog: default_2.ForwardRefExoticComponent<NiceAdminAuditLogProps & default_2.RefAttributes<HTMLDivElement>>;
127
+
128
+ /** Props for {@link NiceAdminAuditLog}. */
129
+ export declare interface NiceAdminAuditLogProps {
130
+ /** Log entries. */
131
+ entries: AuditLogEntry[];
132
+ /** Called when an entry is clicked for details. */
133
+ onEntryClick?: (entry: AuditLogEntry) => void;
134
+ /** Called when requesting more entries. */
135
+ onLoadMore?: () => void;
136
+ /** Whether more entries are available. */
137
+ hasMore?: boolean;
138
+ /** Whether to show search. */
139
+ searchable?: boolean;
140
+ /** Whether to show severity filter. */
141
+ showSeverityFilter?: boolean;
142
+ /** Title. */
143
+ title?: string;
144
+ className?: string;
145
+ style?: default_2.CSSProperties;
146
+ }
147
+
148
+ /**
149
+ * {@link NiceAdminDashboard} — Admin dashboard with configurable widget grid.
150
+ */
151
+ export declare const NiceAdminDashboard: default_2.ForwardRefExoticComponent<NiceAdminDashboardProps & default_2.RefAttributes<HTMLDivElement>>;
152
+
153
+ /** Props for {@link NiceAdminDashboard}. */
154
+ export declare interface NiceAdminDashboardProps {
155
+ /** Dashboard widgets. */
156
+ widgets: AdminWidget[];
157
+ /** Number of grid columns (default 4). */
158
+ columns?: number;
159
+ /** Title. */
160
+ title?: string;
161
+ /** Header action buttons. */
162
+ headerActions?: default_2.ReactNode;
163
+ /** Called when a widget is clicked. */
164
+ onWidgetClick?: (widget: AdminWidget) => void;
165
+ className?: string;
166
+ style?: default_2.CSSProperties;
167
+ }
168
+
169
+ /**
170
+ * {@link NiceAdminNotifications} — Notification management panel.
171
+ */
172
+ export declare const NiceAdminNotifications: default_2.ForwardRefExoticComponent<NiceAdminNotificationsProps & default_2.RefAttributes<HTMLDivElement>>;
173
+
174
+ /** Props for {@link NiceAdminNotifications}. */
175
+ export declare interface NiceAdminNotificationsProps {
176
+ /** Notification definitions. */
177
+ notifications: AdminNotification[];
178
+ /** Available channels. */
179
+ availableChannels?: NotificationChannel[];
180
+ /** Called when toggling enabled. */
181
+ onToggle?: (id: string, enabled: boolean) => void;
182
+ /** Called when editing a notification. */
183
+ onEdit?: (notification: AdminNotification) => void;
184
+ /** Called when testing a notification. */
185
+ onTest?: (id: string) => void;
186
+ /** Called when creating a notification. */
187
+ onCreate?: () => void;
188
+ /** Called when deleting a notification. */
189
+ onDelete?: (id: string) => void;
190
+ /** Title. */
191
+ title?: string;
192
+ className?: string;
193
+ style?: default_2.CSSProperties;
194
+ }
195
+
196
+ /**
197
+ * {@link NiceAdminRoles} — Role management with permission matrix grid.
198
+ */
199
+ export declare const NiceAdminRoles: default_2.ForwardRefExoticComponent<NiceAdminRolesProps & default_2.RefAttributes<HTMLDivElement>>;
200
+
201
+ /** Props for {@link NiceAdminRoles}. */
202
+ export declare interface NiceAdminRolesProps {
203
+ /** Roles. */
204
+ roles: AdminRole[];
205
+ /** Available permission actions. */
206
+ actions: PermissionAction[];
207
+ /** Available permission resources. */
208
+ resources: PermissionResource[];
209
+ /** Called when role permissions change. */
210
+ onPermissionChange?: (roleId: string, resourceId: string, actionId: string, granted: boolean) => void;
211
+ /** Called when creating a role. */
212
+ onCreate?: (name: string, description: string) => void;
213
+ /** Called when deleting a role. */
214
+ onDelete?: (roleId: string) => void;
215
+ /** Called when renaming a role. */
216
+ onRename?: (roleId: string, name: string) => void;
217
+ /** Title. */
218
+ title?: string;
219
+ className?: string;
220
+ style?: default_2.CSSProperties;
221
+ }
222
+
223
+ /**
224
+ * {@link NiceAdminSettings} — System settings editor with sections and validation.
225
+ */
226
+ export declare const NiceAdminSettings: default_2.ForwardRefExoticComponent<NiceAdminSettingsProps & default_2.RefAttributes<HTMLDivElement>>;
227
+
228
+ /** Props for {@link NiceAdminSettings}. */
229
+ export declare interface NiceAdminSettingsProps {
230
+ /** Settings items. */
231
+ settings: SettingItem[];
232
+ /** Called when saving. */
233
+ onSave?: (values: Record<string, unknown>) => void;
234
+ /** Called when a single setting changes. */
235
+ onChange?: (key: string, value: unknown) => void;
236
+ /** Called to reset to defaults. */
237
+ onReset?: () => void;
238
+ /** Whether save button is loading. */
239
+ saving?: boolean;
240
+ /** Title. */
241
+ title?: string;
242
+ className?: string;
243
+ style?: default_2.CSSProperties;
244
+ }
245
+
246
+ /**
247
+ * {@link NiceAdminUsers} — User management table with CRUD and role assignment.
248
+ */
249
+ export declare const NiceAdminUsers: default_2.ForwardRefExoticComponent<NiceAdminUsersProps & default_2.RefAttributes<HTMLDivElement>>;
250
+
251
+ /** Props for {@link NiceAdminUsers}. */
252
+ export declare interface NiceAdminUsersProps {
253
+ /** Users to display. */
254
+ users: AdminUser[];
255
+ /** Available roles for assignment. */
256
+ availableRoles?: string[];
257
+ /** Called when creating a user. */
258
+ onCreate?: () => void;
259
+ /** Called when editing a user. */
260
+ onEdit?: (user: AdminUser) => void;
261
+ /** Called when deleting a user. */
262
+ onDelete?: (userId: string) => void;
263
+ /** Called when toggling user status. */
264
+ onToggleStatus?: (userId: string, status: AdminUser['status']) => void;
265
+ /** Called when changing user roles. */
266
+ onChangeRoles?: (userId: string, roles: string[]) => void;
267
+ /** Whether to show search. */
268
+ searchable?: boolean;
269
+ /** Title. */
270
+ title?: string;
271
+ className?: string;
272
+ style?: default_2.CSSProperties;
273
+ }
274
+
275
+ /**
276
+ * {@link NiceFeatureFlags} — Feature flag management with environment toggles and rollout percentages.
277
+ */
278
+ export declare const NiceFeatureFlags: default_2.ForwardRefExoticComponent<NiceFeatureFlagsProps & default_2.RefAttributes<HTMLDivElement>>;
279
+
280
+ /** Props for {@link NiceFeatureFlags}. */
281
+ export declare interface NiceFeatureFlagsProps {
282
+ /** Feature flags. */
283
+ flags: FeatureFlag[];
284
+ /** Available environment names. */
285
+ environmentNames?: string[];
286
+ /** Called when toggling a flag in an environment. */
287
+ onToggle?: (flagId: string, envName: string, enabled: boolean) => void;
288
+ /** Called when changing rollout percentage. */
289
+ onPercentageChange?: (flagId: string, envName: string, percentage: number) => void;
290
+ /** Called when creating a new flag. */
291
+ onCreate?: (key: string, name: string, description: string) => void;
292
+ /** Called when deleting a flag. */
293
+ onDelete?: (flagId: string) => void;
294
+ /** Called when editing a flag. */
295
+ onEdit?: (flag: FeatureFlag) => void;
296
+ /** Title. */
297
+ title?: string;
298
+ className?: string;
299
+ style?: default_2.CSSProperties;
300
+ }
301
+
302
+ /**
303
+ * {@link NiceImportExport} — Data import/export with format selection, file upload, and job tracking.
304
+ */
305
+ export declare const NiceImportExport: default_2.ForwardRefExoticComponent<NiceImportExportProps & default_2.RefAttributes<HTMLDivElement>>;
306
+
307
+ /** Props for {@link NiceImportExport}. */
308
+ export declare interface NiceImportExportProps {
309
+ /** Available target entities (e.g. "users", "products"). */
310
+ entities: Array<{
311
+ id: string;
312
+ label: string;
313
+ }>;
314
+ /** Available formats. */
315
+ formats?: DataFormat[];
316
+ /** Recent jobs. */
317
+ jobs?: ImportExportJob[];
318
+ /** Called when starting an import. */
319
+ onImport?: (entityId: string, format: DataFormat, file: File, mappings?: ColumnMapping[]) => void;
320
+ /** Called when starting an export. */
321
+ onExport?: (entityId: string, format: DataFormat) => void;
322
+ /** Called when downloading a completed export. */
323
+ onDownload?: (jobId: string) => void;
324
+ /** Available target fields for mapping. */
325
+ targetFields?: string[];
326
+ /** Title. */
327
+ title?: string;
328
+ className?: string;
329
+ style?: default_2.CSSProperties;
330
+ }
331
+
332
+ /** Notification channel. */
333
+ export declare type NotificationChannel = 'email' | 'push' | 'sms' | 'in-app' | 'webhook';
334
+
335
+ /** Permission action. */
336
+ export declare interface PermissionAction {
337
+ id: string;
338
+ label: string;
339
+ description?: string;
340
+ }
341
+
342
+ /** Permission resource. */
343
+ export declare interface PermissionResource {
344
+ id: string;
345
+ label: string;
346
+ category?: string;
347
+ }
348
+
349
+ /** A single setting item. */
350
+ export declare interface SettingItem {
351
+ key: string;
352
+ label: string;
353
+ description?: string;
354
+ type: SettingType;
355
+ value: unknown;
356
+ options?: Array<{
357
+ value: string;
358
+ label: string;
359
+ }>;
360
+ required?: boolean;
361
+ section?: string;
362
+ placeholder?: string;
363
+ }
364
+
365
+ /** Setting value type. */
366
+ export declare type SettingType = 'text' | 'number' | 'boolean' | 'select' | 'textarea' | 'color' | 'password';
367
+
368
+ export { }
package/dist/index.mjs ADDED
@@ -0,0 +1,758 @@
1
+ import { jsxs as n, jsx as e, Fragment as M } from "react/jsx-runtime";
2
+ import { forwardRef as D, useState as x, useMemo as T, useCallback as $ } from "react";
3
+ const P = D(function(S, k) {
4
+ const {
5
+ widgets: u,
6
+ columns: v = 4,
7
+ title: _ = "Dashboard",
8
+ headerActions: g,
9
+ onWidgetClick: h,
10
+ className: b,
11
+ style: f
12
+ } = S;
13
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-admin-dashboard ${b ?? ""}`, style: f, children: [
14
+ /* @__PURE__ */ n("div", { className: "nice-admin-dashboard__header", children: [
15
+ /* @__PURE__ */ e("h2", { children: _ }),
16
+ g && /* @__PURE__ */ e("div", { className: "nice-admin-dashboard__actions", children: g })
17
+ ] }),
18
+ /* @__PURE__ */ e(
19
+ "div",
20
+ {
21
+ className: "nice-admin-dashboard__grid",
22
+ style: {
23
+ display: "grid",
24
+ gridTemplateColumns: `repeat(${v}, 1fr)`,
25
+ gap: 16
26
+ },
27
+ children: u.map((c) => /* @__PURE__ */ n(
28
+ "div",
29
+ {
30
+ className: `nice-admin-dashboard__widget nice-admin-dashboard__widget--${c.type}`,
31
+ style: {
32
+ gridColumn: c.colSpan ? `span ${c.colSpan}` : void 0,
33
+ gridRow: c.rowSpan ? `span ${c.rowSpan}` : void 0
34
+ },
35
+ onClick: () => h == null ? void 0 : h(c),
36
+ role: h ? "button" : void 0,
37
+ tabIndex: h ? 0 : void 0,
38
+ children: [
39
+ /* @__PURE__ */ n("div", { className: "nice-admin-dashboard__widget-header", children: [
40
+ c.icon && /* @__PURE__ */ e("span", { className: "nice-admin-dashboard__widget-icon", children: c.icon }),
41
+ /* @__PURE__ */ e("span", { className: "nice-admin-dashboard__widget-title", children: c.title })
42
+ ] }),
43
+ c.type === "stat" && /* @__PURE__ */ n("div", { className: "nice-admin-dashboard__stat", children: [
44
+ /* @__PURE__ */ e("span", { className: "nice-admin-dashboard__stat-value", children: c.value }),
45
+ c.change && /* @__PURE__ */ e(
46
+ "span",
47
+ {
48
+ className: `nice-admin-dashboard__stat-change ${c.changePositive ? "nice-admin-dashboard__stat-change--positive" : "nice-admin-dashboard__stat-change--negative"}`,
49
+ children: c.change
50
+ }
51
+ )
52
+ ] }),
53
+ c.type === "custom" && c.render && /* @__PURE__ */ e("div", { className: "nice-admin-dashboard__custom", children: c.render() }),
54
+ (c.type === "chart" || c.type === "table" || c.type === "list") && c.render && /* @__PURE__ */ e("div", { className: "nice-admin-dashboard__content", children: c.render() })
55
+ ]
56
+ },
57
+ c.id
58
+ ))
59
+ }
60
+ )
61
+ ] });
62
+ }), q = {
63
+ active: "#22c55e",
64
+ inactive: "#9ca3af",
65
+ suspended: "#ef4444",
66
+ pending: "#eab308"
67
+ }, V = D(function(S, k) {
68
+ const {
69
+ users: u,
70
+ availableRoles: v = [],
71
+ onCreate: _,
72
+ onEdit: g,
73
+ onDelete: h,
74
+ onToggleStatus: b,
75
+ onChangeRoles: f,
76
+ searchable: c = !0,
77
+ title: w = "User Management",
78
+ className: C,
79
+ style: p
80
+ } = S, [N, y] = x(""), [l, t] = x(""), a = T(() => {
81
+ let i = u;
82
+ if (l && (i = i.filter((m) => m.status === l)), N.trim()) {
83
+ const m = N.toLowerCase();
84
+ i = i.filter(
85
+ (L) => L.name.toLowerCase().includes(m) || L.email.toLowerCase().includes(m) || L.roles.some((F) => F.toLowerCase().includes(m))
86
+ );
87
+ }
88
+ return i;
89
+ }, [u, l, N]), o = $((i) => {
90
+ if (!b) return;
91
+ const m = i.status === "active" ? "suspended" : "active";
92
+ b(i.id, m);
93
+ }, [b]);
94
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-admin-users ${C ?? ""}`, style: p, children: [
95
+ /* @__PURE__ */ n("div", { className: "nice-admin-users__header", children: [
96
+ /* @__PURE__ */ e("h3", { children: w }),
97
+ /* @__PURE__ */ n("span", { className: "nice-admin-users__count", children: [
98
+ u.length,
99
+ " users"
100
+ ] }),
101
+ _ && /* @__PURE__ */ e("button", { className: "nice-admin-users__create-btn", onClick: _, children: "+ Add User" })
102
+ ] }),
103
+ /* @__PURE__ */ n("div", { className: "nice-admin-users__toolbar", children: [
104
+ c && /* @__PURE__ */ e(
105
+ "input",
106
+ {
107
+ type: "text",
108
+ value: N,
109
+ onChange: (i) => y(i.target.value),
110
+ placeholder: "Search users…",
111
+ className: "nice-admin-users__search"
112
+ }
113
+ ),
114
+ /* @__PURE__ */ n(
115
+ "select",
116
+ {
117
+ value: l,
118
+ onChange: (i) => t(i.target.value),
119
+ className: "nice-admin-users__status-filter",
120
+ children: [
121
+ /* @__PURE__ */ e("option", { value: "", children: "All statuses" }),
122
+ /* @__PURE__ */ e("option", { value: "active", children: "Active" }),
123
+ /* @__PURE__ */ e("option", { value: "inactive", children: "Inactive" }),
124
+ /* @__PURE__ */ e("option", { value: "suspended", children: "Suspended" }),
125
+ /* @__PURE__ */ e("option", { value: "pending", children: "Pending" })
126
+ ]
127
+ }
128
+ )
129
+ ] }),
130
+ a.length === 0 ? /* @__PURE__ */ e("p", { className: "nice-admin-users__empty", children: "No users found." }) : /* @__PURE__ */ n("table", { className: "nice-admin-users__table", children: [
131
+ /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { children: [
132
+ /* @__PURE__ */ e("th", { children: "User" }),
133
+ /* @__PURE__ */ e("th", { children: "Email" }),
134
+ /* @__PURE__ */ e("th", { children: "Roles" }),
135
+ /* @__PURE__ */ e("th", { children: "Status" }),
136
+ /* @__PURE__ */ e("th", { children: "Created" }),
137
+ /* @__PURE__ */ e("th", { children: "Last Login" }),
138
+ /* @__PURE__ */ e("th", { children: "Actions" })
139
+ ] }) }),
140
+ /* @__PURE__ */ e("tbody", { children: a.map((i) => /* @__PURE__ */ n("tr", { children: [
141
+ /* @__PURE__ */ n("td", { className: "nice-admin-users__user-cell", children: [
142
+ i.avatarUrl && /* @__PURE__ */ e("img", { src: i.avatarUrl, alt: "", className: "nice-admin-users__avatar" }),
143
+ /* @__PURE__ */ e("span", { children: i.name })
144
+ ] }),
145
+ /* @__PURE__ */ e("td", { children: i.email }),
146
+ /* @__PURE__ */ e("td", { children: f ? /* @__PURE__ */ e(
147
+ "select",
148
+ {
149
+ multiple: !0,
150
+ value: i.roles,
151
+ onChange: (m) => {
152
+ const L = Array.from(m.target.selectedOptions, (F) => F.value);
153
+ f(i.id, L);
154
+ },
155
+ className: "nice-admin-users__roles-select",
156
+ children: v.map((m) => /* @__PURE__ */ e("option", { value: m, children: m }, m))
157
+ }
158
+ ) : i.roles.join(", ") }),
159
+ /* @__PURE__ */ e("td", { children: /* @__PURE__ */ e(
160
+ "span",
161
+ {
162
+ className: "nice-admin-users__status-badge",
163
+ style: { backgroundColor: q[i.status] },
164
+ onClick: () => o(i),
165
+ role: b ? "button" : void 0,
166
+ children: i.status
167
+ }
168
+ ) }),
169
+ /* @__PURE__ */ e("td", { children: i.createdAt }),
170
+ /* @__PURE__ */ e("td", { children: i.lastLoginAt ?? "—" }),
171
+ /* @__PURE__ */ n("td", { className: "nice-admin-users__actions", children: [
172
+ g && /* @__PURE__ */ e("button", { onClick: () => g(i), children: "Edit" }),
173
+ h && /* @__PURE__ */ e("button", { onClick: () => h(i.id), children: "Delete" })
174
+ ] })
175
+ ] }, i.id)) })
176
+ ] })
177
+ ] });
178
+ }), Y = D(function(S, k) {
179
+ var d;
180
+ const {
181
+ roles: u,
182
+ actions: v,
183
+ resources: _,
184
+ onPermissionChange: g,
185
+ onCreate: h,
186
+ onDelete: b,
187
+ onRename: f,
188
+ title: c = "Role Management",
189
+ className: w,
190
+ style: C
191
+ } = S, [p, N] = x(((d = u[0]) == null ? void 0 : d.id) ?? null), [y, l] = x(!1), [t, a] = x(""), [o, i] = x(""), m = u.find((r) => r.id === p), L = $(() => {
192
+ !t.trim() || !h || (h(t.trim(), o.trim()), a(""), i(""), l(!1));
193
+ }, [t, o, h]), F = (r, s, A) => {
194
+ var E;
195
+ return ((E = r.permissions[s]) == null ? void 0 : E.includes(A)) ?? !1;
196
+ };
197
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-admin-roles ${w ?? ""}`, style: C, children: [
198
+ /* @__PURE__ */ n("div", { className: "nice-admin-roles__header", children: [
199
+ /* @__PURE__ */ e("h3", { children: c }),
200
+ h && /* @__PURE__ */ e("button", { onClick: () => l(!y), children: "+ New Role" })
201
+ ] }),
202
+ y && /* @__PURE__ */ n("div", { className: "nice-admin-roles__create-form", children: [
203
+ /* @__PURE__ */ e("input", { type: "text", value: t, onChange: (r) => a(r.target.value), placeholder: "Role name" }),
204
+ /* @__PURE__ */ e("input", { type: "text", value: o, onChange: (r) => i(r.target.value), placeholder: "Description" }),
205
+ /* @__PURE__ */ e("button", { onClick: L, disabled: !t.trim(), children: "Create" }),
206
+ /* @__PURE__ */ e("button", { onClick: () => l(!1), children: "Cancel" })
207
+ ] }),
208
+ /* @__PURE__ */ e("div", { className: "nice-admin-roles__tabs", children: u.map((r) => /* @__PURE__ */ n(
209
+ "button",
210
+ {
211
+ className: `nice-admin-roles__tab ${r.id === p ? "nice-admin-roles__tab--active" : ""}`,
212
+ onClick: () => N(r.id),
213
+ style: r.color ? { borderColor: r.color } : void 0,
214
+ children: [
215
+ r.name,
216
+ r.userCount != null && /* @__PURE__ */ n("span", { className: "nice-admin-roles__tab-count", children: [
217
+ "(",
218
+ r.userCount,
219
+ ")"
220
+ ] }),
221
+ r.isSystem && /* @__PURE__ */ e("span", { className: "nice-admin-roles__tab-system", children: "🔒" })
222
+ ]
223
+ },
224
+ r.id
225
+ )) }),
226
+ m && /* @__PURE__ */ n("div", { className: "nice-admin-roles__matrix-wrap", children: [
227
+ m.description && /* @__PURE__ */ e("p", { className: "nice-admin-roles__description", children: m.description }),
228
+ /* @__PURE__ */ n("table", { className: "nice-admin-roles__matrix", children: [
229
+ /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { children: [
230
+ /* @__PURE__ */ e("th", { children: "Resource" }),
231
+ v.map((r) => /* @__PURE__ */ e("th", { title: r.description, children: r.label }, r.id))
232
+ ] }) }),
233
+ /* @__PURE__ */ e("tbody", { children: _.map((r) => /* @__PURE__ */ n("tr", { children: [
234
+ /* @__PURE__ */ e("td", { children: r.label }),
235
+ v.map((s) => {
236
+ const A = F(m, r.id, s.id);
237
+ return /* @__PURE__ */ e("td", { children: /* @__PURE__ */ e(
238
+ "input",
239
+ {
240
+ type: "checkbox",
241
+ checked: A,
242
+ onChange: () => g == null ? void 0 : g(m.id, r.id, s.id, !A),
243
+ disabled: m.isSystem
244
+ }
245
+ ) }, s.id);
246
+ })
247
+ ] }, r.id)) })
248
+ ] }),
249
+ !m.isSystem && /* @__PURE__ */ n("div", { className: "nice-admin-roles__role-actions", children: [
250
+ f && /* @__PURE__ */ e("button", { onClick: () => {
251
+ const r = prompt("New role name:", m.name);
252
+ r && f(m.id, r);
253
+ }, children: "Rename" }),
254
+ b && /* @__PURE__ */ e("button", { onClick: () => b(m.id), children: "Delete Role" })
255
+ ] })
256
+ ] })
257
+ ] });
258
+ }), O = {
259
+ info: { color: "#3b82f6", label: "INFO" },
260
+ warning: { color: "#eab308", label: "WARN" },
261
+ error: { color: "#ef4444", label: "ERROR" },
262
+ critical: { color: "#dc2626", label: "CRIT" }
263
+ }, J = D(function(S, k) {
264
+ const {
265
+ entries: u,
266
+ onEntryClick: v,
267
+ onLoadMore: _,
268
+ hasMore: g = !1,
269
+ searchable: h = !0,
270
+ showSeverityFilter: b = !0,
271
+ title: f = "Audit Log",
272
+ className: c,
273
+ style: w
274
+ } = S, [C, p] = x(""), [N, y] = x(""), l = T(() => {
275
+ let t = u;
276
+ if (N && (t = t.filter((a) => a.severity === N)), C.trim()) {
277
+ const a = C.toLowerCase();
278
+ t = t.filter(
279
+ (o) => {
280
+ var i;
281
+ return o.actorName.toLowerCase().includes(a) || o.action.toLowerCase().includes(a) || o.resource.toLowerCase().includes(a) || ((i = o.details) == null ? void 0 : i.toLowerCase().includes(a));
282
+ }
283
+ );
284
+ }
285
+ return t;
286
+ }, [u, N, C]);
287
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-admin-audit-log ${c ?? ""}`, style: w, children: [
288
+ /* @__PURE__ */ n("div", { className: "nice-admin-audit-log__header", children: [
289
+ /* @__PURE__ */ e("h3", { children: f }),
290
+ /* @__PURE__ */ n("span", { className: "nice-admin-audit-log__count", children: [
291
+ u.length,
292
+ " entries"
293
+ ] })
294
+ ] }),
295
+ /* @__PURE__ */ n("div", { className: "nice-admin-audit-log__toolbar", children: [
296
+ h && /* @__PURE__ */ e(
297
+ "input",
298
+ {
299
+ type: "text",
300
+ value: C,
301
+ onChange: (t) => p(t.target.value),
302
+ placeholder: "Search audit log…",
303
+ className: "nice-admin-audit-log__search"
304
+ }
305
+ ),
306
+ b && /* @__PURE__ */ n(
307
+ "select",
308
+ {
309
+ value: N,
310
+ onChange: (t) => y(t.target.value),
311
+ className: "nice-admin-audit-log__severity-filter",
312
+ children: [
313
+ /* @__PURE__ */ e("option", { value: "", children: "All severities" }),
314
+ /* @__PURE__ */ e("option", { value: "info", children: "Info" }),
315
+ /* @__PURE__ */ e("option", { value: "warning", children: "Warning" }),
316
+ /* @__PURE__ */ e("option", { value: "error", children: "Error" }),
317
+ /* @__PURE__ */ e("option", { value: "critical", children: "Critical" })
318
+ ]
319
+ }
320
+ )
321
+ ] }),
322
+ l.length === 0 ? /* @__PURE__ */ e("p", { className: "nice-admin-audit-log__empty", children: "No audit log entries found." }) : /* @__PURE__ */ n("table", { className: "nice-admin-audit-log__table", children: [
323
+ /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { children: [
324
+ /* @__PURE__ */ e("th", { children: "Timestamp" }),
325
+ /* @__PURE__ */ e("th", { children: "Severity" }),
326
+ /* @__PURE__ */ e("th", { children: "Actor" }),
327
+ /* @__PURE__ */ e("th", { children: "Action" }),
328
+ /* @__PURE__ */ e("th", { children: "Resource" }),
329
+ /* @__PURE__ */ e("th", { children: "IP" }),
330
+ /* @__PURE__ */ e("th", { children: "Details" })
331
+ ] }) }),
332
+ /* @__PURE__ */ e("tbody", { children: l.map((t) => {
333
+ const a = O[t.severity];
334
+ return /* @__PURE__ */ n(
335
+ "tr",
336
+ {
337
+ className: "nice-admin-audit-log__row",
338
+ onClick: () => v == null ? void 0 : v(t),
339
+ role: v ? "button" : void 0,
340
+ tabIndex: v ? 0 : void 0,
341
+ children: [
342
+ /* @__PURE__ */ e("td", { children: t.timestamp }),
343
+ /* @__PURE__ */ e("td", { children: /* @__PURE__ */ e("span", { className: "nice-admin-audit-log__severity", style: { color: a.color }, children: a.label }) }),
344
+ /* @__PURE__ */ e("td", { children: t.actorName }),
345
+ /* @__PURE__ */ e("td", { children: t.action }),
346
+ /* @__PURE__ */ n("td", { children: [
347
+ t.resource,
348
+ t.resourceId ? ` #${t.resourceId}` : ""
349
+ ] }),
350
+ /* @__PURE__ */ e("td", { children: t.ipAddress ?? "—" }),
351
+ /* @__PURE__ */ e("td", { className: "nice-admin-audit-log__details", children: t.details ?? "—" })
352
+ ]
353
+ },
354
+ t.id
355
+ );
356
+ }) })
357
+ ] }),
358
+ g && _ && /* @__PURE__ */ e("button", { className: "nice-admin-audit-log__load-more", onClick: _, children: "Load more" })
359
+ ] });
360
+ }), W = D(function(S, k) {
361
+ const {
362
+ settings: u,
363
+ onSave: v,
364
+ onChange: _,
365
+ onReset: g,
366
+ saving: h = !1,
367
+ title: b = "Settings",
368
+ className: f,
369
+ style: c
370
+ } = S, [w, C] = x(() => {
371
+ const t = {};
372
+ for (const a of u) t[a.key] = a.value;
373
+ return t;
374
+ }), p = $((t, a) => {
375
+ C((o) => ({ ...o, [t]: a })), _ == null || _(t, a);
376
+ }, [_]), N = $(() => {
377
+ v == null || v(w);
378
+ }, [v, w]), y = /* @__PURE__ */ new Map();
379
+ for (const t of u) {
380
+ const a = t.section ?? "General";
381
+ y.has(a) || y.set(a, []), y.get(a).push(t);
382
+ }
383
+ const l = (t) => {
384
+ var o;
385
+ const a = w[t.key];
386
+ switch (t.type) {
387
+ case "boolean":
388
+ return /* @__PURE__ */ n("label", { className: "nice-admin-settings__toggle", children: [
389
+ /* @__PURE__ */ e(
390
+ "input",
391
+ {
392
+ type: "checkbox",
393
+ checked: !!a,
394
+ onChange: (i) => p(t.key, i.target.checked)
395
+ }
396
+ ),
397
+ t.label
398
+ ] });
399
+ case "select":
400
+ return /* @__PURE__ */ e(
401
+ "select",
402
+ {
403
+ value: String(a ?? ""),
404
+ onChange: (i) => p(t.key, i.target.value),
405
+ className: "nice-admin-settings__select",
406
+ children: (o = t.options) == null ? void 0 : o.map((i) => /* @__PURE__ */ e("option", { value: i.value, children: i.label }, i.value))
407
+ }
408
+ );
409
+ case "textarea":
410
+ return /* @__PURE__ */ e(
411
+ "textarea",
412
+ {
413
+ value: String(a ?? ""),
414
+ onChange: (i) => p(t.key, i.target.value),
415
+ placeholder: t.placeholder,
416
+ className: "nice-admin-settings__textarea",
417
+ rows: 4
418
+ }
419
+ );
420
+ case "number":
421
+ return /* @__PURE__ */ e(
422
+ "input",
423
+ {
424
+ type: "number",
425
+ value: a != null ? Number(a) : "",
426
+ onChange: (i) => p(t.key, parseFloat(i.target.value) || 0),
427
+ placeholder: t.placeholder,
428
+ className: "nice-admin-settings__input"
429
+ }
430
+ );
431
+ case "color":
432
+ return /* @__PURE__ */ e(
433
+ "input",
434
+ {
435
+ type: "color",
436
+ value: String(a ?? "#000000"),
437
+ onChange: (i) => p(t.key, i.target.value),
438
+ className: "nice-admin-settings__color"
439
+ }
440
+ );
441
+ case "password":
442
+ return /* @__PURE__ */ e(
443
+ "input",
444
+ {
445
+ type: "password",
446
+ value: String(a ?? ""),
447
+ onChange: (i) => p(t.key, i.target.value),
448
+ placeholder: t.placeholder,
449
+ className: "nice-admin-settings__input",
450
+ autoComplete: "new-password"
451
+ }
452
+ );
453
+ default:
454
+ return /* @__PURE__ */ e(
455
+ "input",
456
+ {
457
+ type: "text",
458
+ value: String(a ?? ""),
459
+ onChange: (i) => p(t.key, i.target.value),
460
+ placeholder: t.placeholder,
461
+ className: "nice-admin-settings__input"
462
+ }
463
+ );
464
+ }
465
+ };
466
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-admin-settings ${f ?? ""}`, style: c, children: [
467
+ /* @__PURE__ */ e("div", { className: "nice-admin-settings__header", children: /* @__PURE__ */ e("h3", { children: b }) }),
468
+ Array.from(y.entries()).map(([t, a]) => /* @__PURE__ */ n("fieldset", { className: "nice-admin-settings__section", children: [
469
+ /* @__PURE__ */ e("legend", { children: t }),
470
+ a.map((o) => /* @__PURE__ */ n("div", { className: "nice-admin-settings__field", children: [
471
+ o.type !== "boolean" && /* @__PURE__ */ n("label", { className: "nice-admin-settings__label", children: [
472
+ o.label,
473
+ o.required && /* @__PURE__ */ e("span", { className: "nice-admin-settings__required", children: "*" })
474
+ ] }),
475
+ o.description && /* @__PURE__ */ e("p", { className: "nice-admin-settings__description", children: o.description }),
476
+ l(o)
477
+ ] }, o.key))
478
+ ] }, t)),
479
+ /* @__PURE__ */ n("div", { className: "nice-admin-settings__actions", children: [
480
+ /* @__PURE__ */ e("button", { className: "nice-admin-settings__save-btn", onClick: N, disabled: h, children: h ? "Saving…" : "Save Settings" }),
481
+ g && /* @__PURE__ */ e("button", { className: "nice-admin-settings__reset-btn", onClick: g, children: "Reset to Defaults" })
482
+ ] })
483
+ ] });
484
+ }), z = D(function(S, k) {
485
+ const {
486
+ notifications: u,
487
+ availableChannels: v = ["email", "push", "sms", "in-app", "webhook"],
488
+ onToggle: _,
489
+ onEdit: g,
490
+ onTest: h,
491
+ onCreate: b,
492
+ onDelete: f,
493
+ title: c = "Notification Management",
494
+ className: w,
495
+ style: C
496
+ } = S, [p, N] = x(""), y = T(() => {
497
+ if (!p.trim()) return u;
498
+ const l = p.toLowerCase();
499
+ return u.filter(
500
+ (t) => {
501
+ var a;
502
+ return t.name.toLowerCase().includes(l) || t.event.toLowerCase().includes(l) || ((a = t.description) == null ? void 0 : a.toLowerCase().includes(l));
503
+ }
504
+ );
505
+ }, [u, p]);
506
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-admin-notifications ${w ?? ""}`, style: C, children: [
507
+ /* @__PURE__ */ n("div", { className: "nice-admin-notifications__header", children: [
508
+ /* @__PURE__ */ e("h3", { children: c }),
509
+ b && /* @__PURE__ */ e("button", { onClick: b, children: "+ New Notification" })
510
+ ] }),
511
+ /* @__PURE__ */ e(
512
+ "input",
513
+ {
514
+ type: "text",
515
+ value: p,
516
+ onChange: (l) => N(l.target.value),
517
+ placeholder: "Search notifications…",
518
+ className: "nice-admin-notifications__search"
519
+ }
520
+ ),
521
+ y.length === 0 ? /* @__PURE__ */ e("p", { className: "nice-admin-notifications__empty", children: "No notifications found." }) : /* @__PURE__ */ n("table", { className: "nice-admin-notifications__table", children: [
522
+ /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { children: [
523
+ /* @__PURE__ */ e("th", { children: "Enabled" }),
524
+ /* @__PURE__ */ e("th", { children: "Name" }),
525
+ /* @__PURE__ */ e("th", { children: "Event" }),
526
+ /* @__PURE__ */ e("th", { children: "Channels" }),
527
+ /* @__PURE__ */ e("th", { children: "Last Sent" }),
528
+ /* @__PURE__ */ e("th", { children: "Sent" }),
529
+ /* @__PURE__ */ e("th", { children: "Actions" })
530
+ ] }) }),
531
+ /* @__PURE__ */ e("tbody", { children: y.map((l) => /* @__PURE__ */ n("tr", { children: [
532
+ /* @__PURE__ */ e("td", { children: /* @__PURE__ */ e(
533
+ "input",
534
+ {
535
+ type: "checkbox",
536
+ checked: l.enabled,
537
+ onChange: () => _ == null ? void 0 : _(l.id, !l.enabled)
538
+ }
539
+ ) }),
540
+ /* @__PURE__ */ n("td", { children: [
541
+ /* @__PURE__ */ e("strong", { children: l.name }),
542
+ l.description && /* @__PURE__ */ e("br", {}),
543
+ l.description && /* @__PURE__ */ e("small", { children: l.description })
544
+ ] }),
545
+ /* @__PURE__ */ e("td", { children: /* @__PURE__ */ e("code", { children: l.event }) }),
546
+ /* @__PURE__ */ e("td", { children: l.channels.join(", ") }),
547
+ /* @__PURE__ */ e("td", { children: l.lastSentAt ?? "—" }),
548
+ /* @__PURE__ */ e("td", { children: l.sentCount ?? 0 }),
549
+ /* @__PURE__ */ n("td", { className: "nice-admin-notifications__actions", children: [
550
+ g && /* @__PURE__ */ e("button", { onClick: () => g(l), children: "Edit" }),
551
+ h && /* @__PURE__ */ e("button", { onClick: () => h(l.id), children: "Test" }),
552
+ f && /* @__PURE__ */ e("button", { onClick: () => f(l.id), children: "Delete" })
553
+ ] })
554
+ ] }, l.id)) })
555
+ ] })
556
+ ] });
557
+ }), B = D(function(S, k) {
558
+ const {
559
+ flags: u,
560
+ environmentNames: v = ["development", "staging", "production"],
561
+ onToggle: _,
562
+ onPercentageChange: g,
563
+ onCreate: h,
564
+ onDelete: b,
565
+ onEdit: f,
566
+ title: c = "Feature Flags",
567
+ className: w,
568
+ style: C
569
+ } = S, [p, N] = x(""), [y, l] = x(!1), [t, a] = x(""), [o, i] = x(""), [m, L] = x(""), F = T(() => {
570
+ if (!p.trim()) return u;
571
+ const s = p.toLowerCase();
572
+ return u.filter(
573
+ (A) => {
574
+ var E, R;
575
+ return A.key.toLowerCase().includes(s) || A.name.toLowerCase().includes(s) || ((E = A.description) == null ? void 0 : E.toLowerCase().includes(s)) || ((R = A.tags) == null ? void 0 : R.some((U) => U.toLowerCase().includes(s)));
576
+ }
577
+ );
578
+ }, [u, p]), d = $(() => {
579
+ !t.trim() || !o.trim() || !h || (h(t.trim(), o.trim(), m.trim()), a(""), i(""), L(""), l(!1));
580
+ }, [t, o, m, h]), r = (s, A) => s.environments.find((E) => E.name === A);
581
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-feature-flags ${w ?? ""}`, style: C, children: [
582
+ /* @__PURE__ */ n("div", { className: "nice-feature-flags__header", children: [
583
+ /* @__PURE__ */ e("h3", { children: c }),
584
+ /* @__PURE__ */ n("span", { className: "nice-feature-flags__count", children: [
585
+ u.length,
586
+ " flags"
587
+ ] }),
588
+ h && /* @__PURE__ */ e("button", { onClick: () => l(!y), children: "+ New Flag" })
589
+ ] }),
590
+ y && /* @__PURE__ */ n("div", { className: "nice-feature-flags__create-form", children: [
591
+ /* @__PURE__ */ e("input", { type: "text", value: t, onChange: (s) => a(s.target.value), placeholder: "flag_key" }),
592
+ /* @__PURE__ */ e("input", { type: "text", value: o, onChange: (s) => i(s.target.value), placeholder: "Display name" }),
593
+ /* @__PURE__ */ e("input", { type: "text", value: m, onChange: (s) => L(s.target.value), placeholder: "Description" }),
594
+ /* @__PURE__ */ e("button", { onClick: d, disabled: !t.trim() || !o.trim(), children: "Create" }),
595
+ /* @__PURE__ */ e("button", { onClick: () => l(!1), children: "Cancel" })
596
+ ] }),
597
+ /* @__PURE__ */ e(
598
+ "input",
599
+ {
600
+ type: "text",
601
+ value: p,
602
+ onChange: (s) => N(s.target.value),
603
+ placeholder: "Search flags…",
604
+ className: "nice-feature-flags__search"
605
+ }
606
+ ),
607
+ F.length === 0 ? /* @__PURE__ */ e("p", { className: "nice-feature-flags__empty", children: "No feature flags found." }) : /* @__PURE__ */ n("table", { className: "nice-feature-flags__table", children: [
608
+ /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { children: [
609
+ /* @__PURE__ */ e("th", { children: "Flag" }),
610
+ v.map((s) => /* @__PURE__ */ e("th", { children: s }, s)),
611
+ /* @__PURE__ */ e("th", { children: "Tags" }),
612
+ /* @__PURE__ */ e("th", { children: "Updated" }),
613
+ /* @__PURE__ */ e("th", { children: "Actions" })
614
+ ] }) }),
615
+ /* @__PURE__ */ e("tbody", { children: F.map((s) => {
616
+ var A;
617
+ return /* @__PURE__ */ n("tr", { children: [
618
+ /* @__PURE__ */ e("td", { children: /* @__PURE__ */ n("div", { className: "nice-feature-flags__flag-info", children: [
619
+ /* @__PURE__ */ e("strong", { children: s.name }),
620
+ /* @__PURE__ */ e("code", { className: "nice-feature-flags__key", children: s.key }),
621
+ s.description && /* @__PURE__ */ e("small", { children: s.description })
622
+ ] }) }),
623
+ v.map((E) => {
624
+ const R = r(s, E);
625
+ return /* @__PURE__ */ n("td", { className: "nice-feature-flags__env-cell", children: [
626
+ /* @__PURE__ */ e(
627
+ "input",
628
+ {
629
+ type: "checkbox",
630
+ checked: (R == null ? void 0 : R.enabled) ?? !1,
631
+ onChange: () => _ == null ? void 0 : _(s.id, E, !((R == null ? void 0 : R.enabled) ?? !1))
632
+ }
633
+ ),
634
+ (R == null ? void 0 : R.percentage) != null && /* @__PURE__ */ e(
635
+ "input",
636
+ {
637
+ type: "number",
638
+ min: 0,
639
+ max: 100,
640
+ value: R.percentage,
641
+ onChange: (U) => g == null ? void 0 : g(s.id, E, parseInt(U.target.value, 10) || 0),
642
+ className: "nice-feature-flags__percentage",
643
+ title: "Rollout %"
644
+ }
645
+ )
646
+ ] }, E);
647
+ }),
648
+ /* @__PURE__ */ e("td", { children: ((A = s.tags) == null ? void 0 : A.join(", ")) || "—" }),
649
+ /* @__PURE__ */ e("td", { children: s.updatedAt ?? s.createdAt }),
650
+ /* @__PURE__ */ n("td", { className: "nice-feature-flags__actions", children: [
651
+ f && /* @__PURE__ */ e("button", { onClick: () => f(s), children: "Edit" }),
652
+ b && /* @__PURE__ */ e("button", { onClick: () => b(s.id), children: "Delete" })
653
+ ] })
654
+ ] }, s.id);
655
+ }) })
656
+ ] })
657
+ ] });
658
+ }), H = D(function(S, k) {
659
+ var F;
660
+ const {
661
+ entities: u,
662
+ formats: v = ["json", "csv", "xlsx"],
663
+ jobs: _ = [],
664
+ onImport: g,
665
+ onExport: h,
666
+ onDownload: b,
667
+ title: f = "Import / Export",
668
+ className: c,
669
+ style: w
670
+ } = S, [C, p] = x("export"), [N, y] = x(((F = u[0]) == null ? void 0 : F.id) ?? ""), [l, t] = x(v[0] ?? "json"), [a, o] = x(null), i = $(() => {
671
+ !g || !a || !N || (g(N, l, a), o(null));
672
+ }, [g, N, l, a]), m = $(() => {
673
+ !h || !N || h(N, l);
674
+ }, [h, N, l]), L = (d) => {
675
+ var r;
676
+ o(((r = d.target.files) == null ? void 0 : r[0]) ?? null);
677
+ };
678
+ return /* @__PURE__ */ n("div", { ref: k, className: `nice-import-export ${c ?? ""}`, style: w, children: [
679
+ /* @__PURE__ */ e("div", { className: "nice-import-export__header", children: /* @__PURE__ */ e("h3", { children: f }) }),
680
+ /* @__PURE__ */ n("div", { className: "nice-import-export__tabs", children: [
681
+ /* @__PURE__ */ e(
682
+ "button",
683
+ {
684
+ className: `nice-import-export__tab ${C === "import" ? "nice-import-export__tab--active" : ""}`,
685
+ onClick: () => p("import"),
686
+ children: "Import"
687
+ }
688
+ ),
689
+ /* @__PURE__ */ e(
690
+ "button",
691
+ {
692
+ className: `nice-import-export__tab ${C === "export" ? "nice-import-export__tab--active" : ""}`,
693
+ onClick: () => p("export"),
694
+ children: "Export"
695
+ }
696
+ )
697
+ ] }),
698
+ /* @__PURE__ */ n("div", { className: "nice-import-export__form", children: [
699
+ /* @__PURE__ */ n("label", { children: [
700
+ "Entity",
701
+ /* @__PURE__ */ e("select", { value: N, onChange: (d) => y(d.target.value), children: u.map((d) => /* @__PURE__ */ e("option", { value: d.id, children: d.label }, d.id)) })
702
+ ] }),
703
+ /* @__PURE__ */ n("label", { children: [
704
+ "Format",
705
+ /* @__PURE__ */ e("select", { value: l, onChange: (d) => t(d.target.value), children: v.map((d) => /* @__PURE__ */ e("option", { value: d, children: d.toUpperCase() }, d)) })
706
+ ] }),
707
+ C === "import" && /* @__PURE__ */ n(M, { children: [
708
+ /* @__PURE__ */ n("label", { children: [
709
+ "File",
710
+ /* @__PURE__ */ e("input", { type: "file", onChange: L, accept: `.${l}` })
711
+ ] }),
712
+ /* @__PURE__ */ e(
713
+ "button",
714
+ {
715
+ className: "nice-import-export__action-btn",
716
+ onClick: i,
717
+ disabled: !a,
718
+ children: "Start Import"
719
+ }
720
+ )
721
+ ] }),
722
+ C === "export" && /* @__PURE__ */ e("button", { className: "nice-import-export__action-btn", onClick: m, children: "Start Export" })
723
+ ] }),
724
+ _.length > 0 && /* @__PURE__ */ n("div", { className: "nice-import-export__jobs", children: [
725
+ /* @__PURE__ */ e("h4", { children: "Recent Jobs" }),
726
+ /* @__PURE__ */ n("table", { className: "nice-import-export__jobs-table", children: [
727
+ /* @__PURE__ */ e("thead", { children: /* @__PURE__ */ n("tr", { children: [
728
+ /* @__PURE__ */ e("th", { children: "Type" }),
729
+ /* @__PURE__ */ e("th", { children: "Format" }),
730
+ /* @__PURE__ */ e("th", { children: "Status" }),
731
+ /* @__PURE__ */ e("th", { children: "Progress" }),
732
+ /* @__PURE__ */ e("th", { children: "Errors" }),
733
+ /* @__PURE__ */ e("th", { children: "Created" }),
734
+ /* @__PURE__ */ e("th", {})
735
+ ] }) }),
736
+ /* @__PURE__ */ e("tbody", { children: _.map((d) => /* @__PURE__ */ n("tr", { children: [
737
+ /* @__PURE__ */ e("td", { children: d.type }),
738
+ /* @__PURE__ */ e("td", { children: d.format.toUpperCase() }),
739
+ /* @__PURE__ */ e("td", { children: /* @__PURE__ */ e("span", { className: `nice-import-export__status nice-import-export__status--${d.status}`, children: d.status }) }),
740
+ /* @__PURE__ */ e("td", { children: d.processedRows != null && d.totalRows ? `${d.processedRows} / ${d.totalRows}` : "—" }),
741
+ /* @__PURE__ */ e("td", { children: d.errorCount ?? 0 }),
742
+ /* @__PURE__ */ e("td", { children: d.createdAt }),
743
+ /* @__PURE__ */ e("td", { children: d.type === "export" && d.status === "completed" && b && /* @__PURE__ */ e("button", { onClick: () => b(d.id), children: "Download" }) })
744
+ ] }, d.id)) })
745
+ ] })
746
+ ] })
747
+ ] });
748
+ });
749
+ export {
750
+ J as NiceAdminAuditLog,
751
+ P as NiceAdminDashboard,
752
+ z as NiceAdminNotifications,
753
+ Y as NiceAdminRoles,
754
+ W as NiceAdminSettings,
755
+ V as NiceAdminUsers,
756
+ B as NiceFeatureFlags,
757
+ H as NiceImportExport
758
+ };
package/package.json ADDED
@@ -0,0 +1,58 @@
1
+ {
2
+ "name": "@nice2dev/admin",
3
+ "version": "0.1.0",
4
+ "description": "Nice2Dev Admin — Dashboard, user management, roles, audit log, settings, feature flags, import/export for React",
5
+ "type": "module",
6
+ "main": "dist/index.cjs",
7
+ "module": "dist/index.mjs",
8
+ "types": "dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.mjs",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./style.css": "./dist/style.css"
16
+ },
17
+ "files": ["dist", "LICENSE", "CHANGELOG.md", "README.md"],
18
+ "sideEffects": ["*.css"],
19
+ "scripts": {
20
+ "dev": "vite",
21
+ "build": "tsc -p tsconfig.build.json && vite build",
22
+ "typecheck": "tsc --noEmit",
23
+ "test": "vitest run --config vitest.config.ts",
24
+ "test:watch": "vitest --config vitest.config.ts",
25
+ "test:coverage": "vitest run --config vitest.config.ts --coverage",
26
+ "clean": "rimraf dist",
27
+ "prepublishOnly": "npm run build"
28
+ },
29
+ "keywords": [
30
+ "react", "admin", "dashboard", "users", "roles", "audit", "settings",
31
+ "feature-flags", "import", "export", "nicetodev"
32
+ ],
33
+ "author": "NiceToDev <contact@nicetodev.com>",
34
+ "license": "MIT",
35
+ "repository": {
36
+ "type": "git",
37
+ "url": "git+https://github.com/NiceToDev/NiceToDev.UI.git",
38
+ "directory": "nice2dev-admin"
39
+ },
40
+ "homepage": "https://github.com/NiceToDev/NiceToDev.UI#readme",
41
+ "bugs": {
42
+ "url": "https://github.com/NiceToDev/NiceToDev.UI/issues"
43
+ },
44
+ "peerDependencies": {
45
+ "react": ">=17.0.0",
46
+ "react-dom": ">=17.0.0"
47
+ },
48
+ "devDependencies": {
49
+ "@types/react": "^18.2.0",
50
+ "@types/react-dom": "^18.2.0",
51
+ "@vitejs/plugin-react": "^4.2.0",
52
+ "react": "^18.2.0",
53
+ "react-dom": "^18.2.0",
54
+ "typescript": "^5.3.0",
55
+ "vite": "^6.2.0",
56
+ "vite-plugin-dts": "^4.5.0"
57
+ }
58
+ }