com-angel-authorization 1.0.0 → 1.0.2

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.
@@ -120,13 +120,501 @@ function Can({
120
120
  return /* @__PURE__ */ jsx(Fragment, { children: allowed ? children : fallback });
121
121
  }
122
122
 
123
+ // src/react/ResourceManager.tsx
124
+ import {
125
+ useCallback as useCallback2,
126
+ useEffect as useEffect2,
127
+ useMemo as useMemo2,
128
+ useState as useState2
129
+ } from "react";
130
+ import {
131
+ RESOURCE_PRIVATE_OPTIONS,
132
+ RESOURCE_STATUS_ENABLED,
133
+ RESOURCE_STATUS_OPTIONS
134
+ } from "../resources";
135
+ import { jsx as jsx2, jsxs } from "react/jsx-runtime";
136
+ var PAGE_SIZE_OPTIONS = ["10", "20", "50", "100"];
137
+ var emptyForm = () => ({
138
+ name: "",
139
+ identification: "",
140
+ status: RESOURCE_STATUS_ENABLED,
141
+ private: false,
142
+ description: ""
143
+ });
144
+ function ResourceManager({
145
+ api,
146
+ title = "\u6743\u9650\u70B9\u7BA1\u7406",
147
+ pageSize: initialPageSize = "20",
148
+ toolbarExtra
149
+ }) {
150
+ const [records, setRecords] = useState2([]);
151
+ const [loading, setLoading] = useState2(false);
152
+ const [error, setError] = useState2("");
153
+ const [pageSize, setPageSize] = useState2(initialPageSize);
154
+ const [pageToken, setPageToken] = useState2("");
155
+ const [hasPreviousPage, setHasPreviousPage] = useState2(false);
156
+ const [hasNextPage, setHasNextPage] = useState2(false);
157
+ const [dialogOpen, setDialogOpen] = useState2(false);
158
+ const [editing, setEditing] = useState2(null);
159
+ const [form, setForm] = useState2(emptyForm);
160
+ const [saving, setSaving] = useState2(false);
161
+ const loadList = useCallback2(
162
+ async (direction = "current", token = pageToken) => {
163
+ setLoading(true);
164
+ setError("");
165
+ try {
166
+ const result = await api.list({
167
+ pagination: {
168
+ pageToken: token,
169
+ pageSize,
170
+ pageDirection: direction
171
+ }
172
+ });
173
+ setRecords(result.records);
174
+ setPageToken(result.pageToken);
175
+ setHasPreviousPage(result.hasPreviousPage);
176
+ setHasNextPage(result.hasNextPage);
177
+ } catch (err) {
178
+ setError(err instanceof Error ? err.message : "\u52A0\u8F7D\u5931\u8D25");
179
+ } finally {
180
+ setLoading(false);
181
+ }
182
+ },
183
+ [api, pageSize, pageToken]
184
+ );
185
+ useEffect2(() => {
186
+ void loadList("current", "");
187
+ }, [api, pageSize]);
188
+ const openCreate = () => {
189
+ setEditing(null);
190
+ setForm(emptyForm());
191
+ setDialogOpen(true);
192
+ };
193
+ const openEdit = (row) => {
194
+ setEditing(row);
195
+ setForm({
196
+ name: row.name,
197
+ identification: row.identification,
198
+ status: row.status,
199
+ private: row.private,
200
+ description: row.description
201
+ });
202
+ setDialogOpen(true);
203
+ };
204
+ const closeDialog = () => {
205
+ if (saving) return;
206
+ setDialogOpen(false);
207
+ };
208
+ const handleSubmit = async (event) => {
209
+ event.preventDefault();
210
+ if (!form.name.trim()) {
211
+ setError("\u8BF7\u586B\u5199\u6743\u9650\u540D\u79F0");
212
+ return;
213
+ }
214
+ if (!form.identification.trim()) {
215
+ setError("\u8BF7\u586B\u5199\u63A5\u53E3\u6807\u8BC6");
216
+ return;
217
+ }
218
+ setSaving(true);
219
+ setError("");
220
+ try {
221
+ if (editing) {
222
+ await api.update(editing.resourceId, form);
223
+ } else {
224
+ await api.create(form);
225
+ }
226
+ setDialogOpen(false);
227
+ await loadList("current", "");
228
+ } catch (err) {
229
+ setError(err instanceof Error ? err.message : "\u4FDD\u5B58\u5931\u8D25");
230
+ } finally {
231
+ setSaving(false);
232
+ }
233
+ };
234
+ const handleDelete = async (row) => {
235
+ if (!window.confirm(`\u786E\u8BA4\u5220\u9664\u6743\u9650\u70B9\u300C${row.name}\u300D\uFF1F`)) return;
236
+ setError("");
237
+ try {
238
+ await api.remove(row.resourceId);
239
+ await loadList("current", "");
240
+ } catch (err) {
241
+ setError(err instanceof Error ? err.message : "\u5220\u9664\u5931\u8D25");
242
+ }
243
+ };
244
+ const statusLabel = useMemo2(
245
+ () => Object.fromEntries(RESOURCE_STATUS_OPTIONS.map((o) => [o.value, o.label])),
246
+ []
247
+ );
248
+ return /* @__PURE__ */ jsxs("div", { style: styles.root, children: [
249
+ /* @__PURE__ */ jsxs("div", { style: styles.toolbar, children: [
250
+ /* @__PURE__ */ jsx2("h2", { style: styles.title, children: title }),
251
+ /* @__PURE__ */ jsxs("div", { style: styles.toolbarRight, children: [
252
+ toolbarExtra,
253
+ /* @__PURE__ */ jsx2("button", { type: "button", style: styles.primaryBtn, onClick: openCreate, children: "\u65B0\u589E" })
254
+ ] })
255
+ ] }),
256
+ error ? /* @__PURE__ */ jsx2("div", { style: styles.error, children: error }) : null,
257
+ /* @__PURE__ */ jsx2("div", { style: styles.tableWrap, children: /* @__PURE__ */ jsxs("table", { style: styles.table, children: [
258
+ /* @__PURE__ */ jsx2("thead", { children: /* @__PURE__ */ jsxs("tr", { children: [
259
+ /* @__PURE__ */ jsx2("th", { style: styles.th, children: "\u6743\u9650\u540D\u79F0" }),
260
+ /* @__PURE__ */ jsx2("th", { style: styles.th, children: "\u63A5\u53E3\u6807\u8BC6" }),
261
+ /* @__PURE__ */ jsx2("th", { style: styles.th, children: "\u63CF\u8FF0" }),
262
+ /* @__PURE__ */ jsx2("th", { style: { ...styles.th, width: 90 }, children: "\u72B6\u6001" }),
263
+ /* @__PURE__ */ jsx2("th", { style: { ...styles.th, width: 140 }, children: "\u64CD\u4F5C" })
264
+ ] }) }),
265
+ /* @__PURE__ */ jsx2("tbody", { children: loading ? /* @__PURE__ */ jsx2("tr", { children: /* @__PURE__ */ jsx2("td", { colSpan: 5, style: styles.empty, children: "\u52A0\u8F7D\u4E2D\u2026" }) }) : records.length === 0 ? /* @__PURE__ */ jsx2("tr", { children: /* @__PURE__ */ jsx2("td", { colSpan: 5, style: styles.empty, children: "\u6682\u65E0\u6570\u636E" }) }) : records.map((row) => /* @__PURE__ */ jsxs("tr", { children: [
266
+ /* @__PURE__ */ jsx2("td", { style: styles.td, children: row.name }),
267
+ /* @__PURE__ */ jsx2("td", { style: styles.td, children: /* @__PURE__ */ jsx2("code", { style: styles.code, children: row.identification }) }),
268
+ /* @__PURE__ */ jsx2("td", { style: styles.td, children: row.description || "\u2014" }),
269
+ /* @__PURE__ */ jsx2("td", { style: styles.td, children: /* @__PURE__ */ jsx2(
270
+ "span",
271
+ {
272
+ style: {
273
+ ...styles.badge,
274
+ background: row.status === RESOURCE_STATUS_ENABLED ? "#e8f7ef" : "#f4f4f5",
275
+ color: row.status === RESOURCE_STATUS_ENABLED ? "#067647" : "#667085"
276
+ },
277
+ children: statusLabel[row.status] ?? row.status
278
+ }
279
+ ) }),
280
+ /* @__PURE__ */ jsxs("td", { style: styles.td, children: [
281
+ /* @__PURE__ */ jsx2("button", { type: "button", style: styles.linkBtn, onClick: () => openEdit(row), children: "\u7F16\u8F91" }),
282
+ /* @__PURE__ */ jsx2(
283
+ "button",
284
+ {
285
+ type: "button",
286
+ style: { ...styles.linkBtn, color: "#d92d20" },
287
+ onClick: () => void handleDelete(row),
288
+ children: "\u5220\u9664"
289
+ }
290
+ )
291
+ ] })
292
+ ] }, row.resourceId)) })
293
+ ] }) }),
294
+ /* @__PURE__ */ jsxs("div", { style: styles.pagination, children: [
295
+ /* @__PURE__ */ jsxs("label", { style: styles.pageSize, children: [
296
+ "\u6BCF\u9875",
297
+ /* @__PURE__ */ jsx2(
298
+ "select",
299
+ {
300
+ value: pageSize,
301
+ onChange: (e) => {
302
+ setPageToken("");
303
+ setPageSize(e.target.value);
304
+ },
305
+ style: styles.select,
306
+ children: PAGE_SIZE_OPTIONS.map((size) => /* @__PURE__ */ jsx2("option", { value: size, children: size }, size))
307
+ }
308
+ )
309
+ ] }),
310
+ /* @__PURE__ */ jsxs("div", { style: styles.pageBtns, children: [
311
+ /* @__PURE__ */ jsx2(
312
+ "button",
313
+ {
314
+ type: "button",
315
+ style: styles.secondaryBtn,
316
+ disabled: !hasPreviousPage || loading,
317
+ onClick: () => void loadList("previous"),
318
+ children: "\u4E0A\u4E00\u9875"
319
+ }
320
+ ),
321
+ /* @__PURE__ */ jsx2(
322
+ "button",
323
+ {
324
+ type: "button",
325
+ style: styles.secondaryBtn,
326
+ disabled: !hasNextPage || loading,
327
+ onClick: () => void loadList("next"),
328
+ children: "\u4E0B\u4E00\u9875"
329
+ }
330
+ )
331
+ ] })
332
+ ] }),
333
+ dialogOpen ? /* @__PURE__ */ jsx2("div", { style: styles.mask, onClick: closeDialog, children: /* @__PURE__ */ jsxs(
334
+ "div",
335
+ {
336
+ style: styles.dialog,
337
+ onClick: (e) => e.stopPropagation(),
338
+ role: "dialog",
339
+ "aria-modal": "true",
340
+ children: [
341
+ /* @__PURE__ */ jsxs("div", { style: styles.dialogHeader, children: [
342
+ /* @__PURE__ */ jsx2("h3", { style: styles.dialogTitle, children: editing ? "\u7F16\u8F91\u6743\u9650\u70B9" : "\u65B0\u589E\u6743\u9650\u70B9" }),
343
+ /* @__PURE__ */ jsx2("button", { type: "button", style: styles.iconBtn, onClick: closeDialog, "aria-label": "\u5173\u95ED", children: "\xD7" })
344
+ ] }),
345
+ /* @__PURE__ */ jsxs("form", { style: styles.form, onSubmit: (e) => void handleSubmit(e), children: [
346
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
347
+ /* @__PURE__ */ jsx2("span", { style: styles.label, children: "\u6743\u9650\u540D\u79F0" }),
348
+ /* @__PURE__ */ jsx2(
349
+ "input",
350
+ {
351
+ style: styles.input,
352
+ value: form.name,
353
+ onChange: (e) => setForm((prev) => ({ ...prev, name: e.target.value })),
354
+ placeholder: "\u8BF7\u8F93\u5165\u6743\u9650\u540D\u79F0",
355
+ required: true
356
+ }
357
+ )
358
+ ] }),
359
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
360
+ /* @__PURE__ */ jsx2("span", { style: styles.label, children: "\u63A5\u53E3\u6807\u8BC6" }),
361
+ /* @__PURE__ */ jsx2(
362
+ "input",
363
+ {
364
+ style: styles.input,
365
+ value: form.identification,
366
+ onChange: (e) => setForm((prev) => ({ ...prev, identification: e.target.value })),
367
+ placeholder: "\u5982 user:list",
368
+ required: true
369
+ }
370
+ )
371
+ ] }),
372
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
373
+ /* @__PURE__ */ jsx2("span", { style: styles.label, children: "\u72B6\u6001" }),
374
+ /* @__PURE__ */ jsx2(
375
+ "select",
376
+ {
377
+ style: styles.input,
378
+ value: form.status,
379
+ onChange: (e) => setForm((prev) => ({
380
+ ...prev,
381
+ status: Number(e.target.value)
382
+ })),
383
+ children: RESOURCE_STATUS_OPTIONS.map((opt) => /* @__PURE__ */ jsx2("option", { value: opt.value, children: opt.label }, opt.value))
384
+ }
385
+ )
386
+ ] }),
387
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
388
+ /* @__PURE__ */ jsx2("span", { style: styles.label, children: "\u79C1\u6709\u8D44\u6E90" }),
389
+ /* @__PURE__ */ jsx2(
390
+ "select",
391
+ {
392
+ style: styles.input,
393
+ value: form.private ? "1" : "0",
394
+ onChange: (e) => setForm((prev) => ({ ...prev, private: e.target.value === "1" })),
395
+ children: RESOURCE_PRIVATE_OPTIONS.map((opt) => /* @__PURE__ */ jsx2("option", { value: opt.value ? "1" : "0", children: opt.label }, String(opt.value)))
396
+ }
397
+ )
398
+ ] }),
399
+ /* @__PURE__ */ jsxs("label", { style: styles.field, children: [
400
+ /* @__PURE__ */ jsx2("span", { style: styles.label, children: "\u63CF\u8FF0" }),
401
+ /* @__PURE__ */ jsx2(
402
+ "textarea",
403
+ {
404
+ style: { ...styles.input, minHeight: 88, resize: "vertical" },
405
+ value: form.description,
406
+ onChange: (e) => setForm((prev) => ({ ...prev, description: e.target.value })),
407
+ placeholder: "\u8BF7\u8F93\u5165\u63CF\u8FF0"
408
+ }
409
+ )
410
+ ] }),
411
+ /* @__PURE__ */ jsxs("div", { style: styles.dialogFooter, children: [
412
+ /* @__PURE__ */ jsx2("button", { type: "button", style: styles.secondaryBtn, onClick: closeDialog, children: "\u53D6\u6D88" }),
413
+ /* @__PURE__ */ jsx2("button", { type: "submit", style: styles.primaryBtn, disabled: saving, children: saving ? "\u4FDD\u5B58\u4E2D\u2026" : "\u4FDD\u5B58" })
414
+ ] })
415
+ ] })
416
+ ]
417
+ }
418
+ ) }) : null
419
+ ] });
420
+ }
421
+ var styles = {
422
+ root: {
423
+ display: "flex",
424
+ flexDirection: "column",
425
+ gap: 16,
426
+ padding: 16,
427
+ color: "#101828",
428
+ fontFamily: '"PingFang SC", "Microsoft YaHei", -apple-system, BlinkMacSystemFont, sans-serif'
429
+ },
430
+ toolbar: {
431
+ display: "flex",
432
+ alignItems: "center",
433
+ justifyContent: "space-between",
434
+ gap: 12
435
+ },
436
+ title: { margin: 0, fontSize: 18, fontWeight: 600 },
437
+ toolbarRight: { display: "flex", alignItems: "center", gap: 8 },
438
+ error: {
439
+ padding: "10px 12px",
440
+ borderRadius: 8,
441
+ background: "#fef3f2",
442
+ color: "#b42318",
443
+ fontSize: 13
444
+ },
445
+ tableWrap: {
446
+ overflow: "auto",
447
+ border: "1px solid #eaecf0",
448
+ borderRadius: 10,
449
+ background: "#fff"
450
+ },
451
+ table: { width: "100%", borderCollapse: "collapse", minWidth: 720 },
452
+ th: {
453
+ textAlign: "left",
454
+ padding: "12px 14px",
455
+ fontSize: 13,
456
+ fontWeight: 600,
457
+ color: "#475467",
458
+ background: "#f9fafb",
459
+ borderBottom: "1px solid #eaecf0"
460
+ },
461
+ td: {
462
+ padding: "12px 14px",
463
+ fontSize: 14,
464
+ borderBottom: "1px solid #f2f4f7",
465
+ verticalAlign: "middle"
466
+ },
467
+ empty: {
468
+ padding: 28,
469
+ textAlign: "center",
470
+ color: "#98a2b3",
471
+ fontSize: 14
472
+ },
473
+ code: {
474
+ fontFamily: "ui-monospace, SFMono-Regular, Menlo, monospace",
475
+ fontSize: 13,
476
+ background: "#f2f4f7",
477
+ padding: "2px 6px",
478
+ borderRadius: 4
479
+ },
480
+ badge: {
481
+ display: "inline-block",
482
+ padding: "2px 8px",
483
+ borderRadius: 999,
484
+ fontSize: 12,
485
+ fontWeight: 500
486
+ },
487
+ linkBtn: {
488
+ border: "none",
489
+ background: "transparent",
490
+ color: "#049BAD",
491
+ cursor: "pointer",
492
+ padding: "0 8px 0 0",
493
+ fontSize: 13
494
+ },
495
+ pagination: {
496
+ display: "flex",
497
+ alignItems: "center",
498
+ justifyContent: "space-between",
499
+ gap: 12
500
+ },
501
+ pageSize: { display: "flex", alignItems: "center", gap: 8, fontSize: 13, color: "#475467" },
502
+ pageBtns: { display: "flex", gap: 8 },
503
+ primaryBtn: {
504
+ border: "none",
505
+ background: "#049BAD",
506
+ color: "#fff",
507
+ borderRadius: 8,
508
+ padding: "8px 14px",
509
+ cursor: "pointer",
510
+ fontSize: 14
511
+ },
512
+ secondaryBtn: {
513
+ border: "1px solid #d0d5dd",
514
+ background: "#fff",
515
+ color: "#344054",
516
+ borderRadius: 8,
517
+ padding: "8px 14px",
518
+ cursor: "pointer",
519
+ fontSize: 14
520
+ },
521
+ select: {
522
+ border: "1px solid #d0d5dd",
523
+ borderRadius: 6,
524
+ padding: "4px 8px",
525
+ fontSize: 13
526
+ },
527
+ mask: {
528
+ position: "fixed",
529
+ inset: 0,
530
+ background: "rgba(16, 24, 40, 0.45)",
531
+ display: "flex",
532
+ alignItems: "center",
533
+ justifyContent: "center",
534
+ zIndex: 1e3,
535
+ padding: 16
536
+ },
537
+ dialog: {
538
+ width: "100%",
539
+ maxWidth: 480,
540
+ background: "#fff",
541
+ borderRadius: 12,
542
+ boxShadow: "0 20px 40px rgba(16,24,40,0.18)"
543
+ },
544
+ dialogHeader: {
545
+ display: "flex",
546
+ alignItems: "center",
547
+ justifyContent: "space-between",
548
+ padding: "14px 16px",
549
+ borderBottom: "1px solid #eaecf0"
550
+ },
551
+ dialogTitle: { margin: 0, fontSize: 16, fontWeight: 600 },
552
+ iconBtn: {
553
+ border: "none",
554
+ background: "transparent",
555
+ fontSize: 22,
556
+ lineHeight: 1,
557
+ cursor: "pointer",
558
+ color: "#667085"
559
+ },
560
+ form: { display: "flex", flexDirection: "column", gap: 12, padding: 16 },
561
+ field: { display: "flex", flexDirection: "column", gap: 6 },
562
+ label: { fontSize: 13, color: "#344054", fontWeight: 500 },
563
+ input: {
564
+ border: "1px solid #d0d5dd",
565
+ borderRadius: 8,
566
+ padding: "8px 10px",
567
+ fontSize: 14,
568
+ outline: "none"
569
+ },
570
+ dialogFooter: {
571
+ display: "flex",
572
+ justifyContent: "flex-end",
573
+ gap: 8,
574
+ paddingTop: 4
575
+ }
576
+ };
577
+
123
578
  // src/react/index.ts
124
579
  import { PermissionStore, createPermissionStore as createPermissionStore2 } from "../core";
580
+ import { getAppClientId, getDeviceWorkerId, snowyflake } from "../utils/snowflake";
581
+ import {
582
+ RESOURCE_PRIVATE_OPTIONS as RESOURCE_PRIVATE_OPTIONS2,
583
+ RESOURCE_STATUS_DISABLED,
584
+ RESOURCE_STATUS_ENABLED as RESOURCE_STATUS_ENABLED2,
585
+ RESOURCE_STATUS_OPTIONS as RESOURCE_STATUS_OPTIONS2,
586
+ RESOURCE_TYPE_API,
587
+ appendQueryParam,
588
+ buildCreateBody,
589
+ buildUpdateBody,
590
+ createAuthorizationResourceApi,
591
+ createDefaultResourceRequest,
592
+ extractPagination,
593
+ extractRecords,
594
+ mapAuthorizationResource
595
+ } from "../resources";
125
596
  export {
126
597
  Can,
127
598
  PermissionProvider,
128
599
  PermissionStore,
600
+ RESOURCE_PRIVATE_OPTIONS2 as RESOURCE_PRIVATE_OPTIONS,
601
+ RESOURCE_STATUS_DISABLED,
602
+ RESOURCE_STATUS_ENABLED2 as RESOURCE_STATUS_ENABLED,
603
+ RESOURCE_STATUS_OPTIONS2 as RESOURCE_STATUS_OPTIONS,
604
+ RESOURCE_TYPE_API,
605
+ ResourceManager,
606
+ appendQueryParam,
607
+ buildCreateBody,
608
+ buildUpdateBody,
609
+ createAuthorizationResourceApi,
610
+ createDefaultResourceRequest,
129
611
  createPermissionStore2 as createPermissionStore,
612
+ extractPagination,
613
+ extractRecords,
614
+ getAppClientId,
615
+ getDeviceWorkerId,
616
+ mapAuthorizationResource,
617
+ snowyflake,
130
618
  useHasPermission,
131
619
  useHasRole,
132
620
  usePermission
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/react/context.tsx","../../src/react/Can.tsx","../../src/react/index.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n createPermissionStore,\n type CheckOptions,\n type PermissionCode,\n type PermissionState,\n type PermissionStore,\n type RoleCode,\n} from '../core';\n\nconst PermissionContext = createContext<PermissionStore | null>(null);\n\nexport interface PermissionProviderProps {\n children: ReactNode;\n /** Pass an existing store to share across trees, or omit to create one. */\n store?: PermissionStore;\n /** Initial state when the provider creates its own store. */\n initialState?: Partial<PermissionState>;\n}\n\nexport function PermissionProvider({\n children,\n store: externalStore,\n initialState,\n}: PermissionProviderProps) {\n const store = useMemo(\n () => externalStore ?? createPermissionStore(initialState),\n // store identity is intentional; initialState only applies on first create\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [externalStore],\n );\n\n return createElement(PermissionContext.Provider, { value: store }, children);\n}\n\nfunction useStore(): PermissionStore {\n const store = useContext(PermissionContext);\n if (!store) {\n throw new Error(\n '[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>.',\n );\n }\n return store;\n}\n\nfunction usePermissionSnapshot(store: PermissionStore): PermissionState {\n const [state, setState] = useState(() => store.getState());\n\n useEffect(() => {\n setState(store.getState());\n return store.subscribe(setState);\n }, [store]);\n\n return state;\n}\n\nexport interface UsePermissionResult {\n permissions: PermissionCode[];\n roles: RoleCode[];\n isSuperAdmin: boolean;\n hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;\n can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n setPermissions: (permissions: PermissionCode[]) => void;\n setRoles: (roles: RoleCode[]) => void;\n setSuperAdmin: (isSuperAdmin: boolean) => void;\n hydrate: (payload: Partial<PermissionState>) => void;\n clear: () => void;\n store: PermissionStore;\n}\n\nexport function usePermission(): UsePermissionResult {\n const store = useStore();\n const state = usePermissionSnapshot(store);\n\n const hasPermission = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) =>\n store.hasPermission(codes, options),\n [store],\n );\n\n const hasRole = useCallback(\n (codes: RoleCode | RoleCode[], options?: CheckOptions) => store.hasRole(codes, options),\n [store],\n );\n\n const can = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => store.can(codes, options),\n [store],\n );\n\n return {\n permissions: state.permissions,\n roles: state.roles,\n isSuperAdmin: Boolean(state.isSuperAdmin),\n hasPermission,\n hasRole,\n can,\n setPermissions: store.setPermissions.bind(store),\n setRoles: store.setRoles.bind(store),\n setSuperAdmin: store.setSuperAdmin.bind(store),\n hydrate: store.hydrate.bind(store),\n clear: store.clear.bind(store),\n store,\n };\n}\n\n/** Returns whether the current user has the given permission(s). */\nexport function useHasPermission(\n codes: PermissionCode | PermissionCode[],\n options?: CheckOptions,\n): boolean {\n const { hasPermission, permissions, isSuperAdmin } = usePermission();\n // re-compute when permission list / super-admin changes\n void permissions;\n void isSuperAdmin;\n return hasPermission(codes, options);\n}\n\n/** Returns whether the current user has the given role(s). */\nexport function useHasRole(\n codes: RoleCode | RoleCode[],\n options?: CheckOptions,\n): boolean {\n const { hasRole, roles, isSuperAdmin } = usePermission();\n void roles;\n void isSuperAdmin;\n return hasRole(codes, options);\n}\n","import type { ReactNode } from 'react';\nimport type { CheckOptions, PermissionCode, RoleCode } from '../core';\nimport { usePermission } from './context';\n\nexport interface CanProps {\n /** Permission codes to check. */\n permission?: PermissionCode | PermissionCode[];\n /** Role codes to check. */\n role?: RoleCode | RoleCode[];\n /**\n * `any` — pass when at least one code matches (default)\n * `all` — pass only when every code matches\n */\n mode?: CheckOptions['mode'];\n /**\n * How permission and role conditions combine when both are provided.\n * Default: `and` (must satisfy both).\n */\n combine?: 'and' | 'or';\n children: ReactNode;\n /** Fallback when access is denied. */\n fallback?: ReactNode;\n}\n\nfunction evaluateAccess(\n hasPermission: (c: PermissionCode | PermissionCode[], o?: CheckOptions) => boolean,\n hasRole: (c: RoleCode | RoleCode[], o?: CheckOptions) => boolean,\n props: Pick<CanProps, 'permission' | 'role' | 'mode' | 'combine'>,\n): boolean {\n const { permission, role, mode, combine = 'and' } = props;\n const options: CheckOptions = { mode };\n\n const hasPermCheck = permission !== undefined;\n const hasRoleCheck = role !== undefined;\n\n if (!hasPermCheck && !hasRoleCheck) return true;\n\n const permOk = hasPermCheck ? hasPermission(permission!, options) : true;\n const roleOk = hasRoleCheck ? hasRole(role!, options) : true;\n\n if (hasPermCheck && hasRoleCheck) {\n return combine === 'or' ? permOk || roleOk : permOk && roleOk;\n }\n\n return hasPermCheck ? permOk : roleOk;\n}\n\n/**\n * Conditionally render children based on permission / role.\n *\n * @example\n * <Can permission=\"user:edit\">\n * <button>Edit</button>\n * </Can>\n *\n * <Can permission={['user:edit', 'user:delete']} mode=\"all\" fallback={null}>\n * <AdminPanel />\n * </Can>\n */\nexport function Can({\n permission,\n role,\n mode,\n combine,\n children,\n fallback = null,\n}: CanProps) {\n const { hasPermission, hasRole } = usePermission();\n const allowed = evaluateAccess(hasPermission, hasRole, {\n permission,\n role,\n mode,\n combine,\n });\n\n return <>{allowed ? children : fallback}</>;\n}\n","export { PermissionProvider, usePermission, useHasPermission, useHasRole } from './context';\nexport type { PermissionProviderProps, UsePermissionResult } from './context';\n\nexport { Can } from './Can';\nexport type { CanProps } from './Can';\n\nexport type {\n CheckOptions,\n MatchMode,\n PermissionChecker,\n PermissionCode,\n PermissionListener,\n PermissionState,\n RoleCode,\n} from '../core';\n\nexport { PermissionStore, createPermissionStore } from '../core';\n"],"mappings":";;;AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAEK;AACP;AAAA,EACE;AAAA,OAMK;AAEP,IAAM,oBAAoB,cAAsC,IAAI;AAU7D,SAAS,mBAAmB;AAAA,EACjC;AAAA,EACA,OAAO;AAAA,EACP;AACF,GAA4B;AAC1B,QAAM,QAAQ;AAAA,IACZ,MAAM,iBAAiB,sBAAsB,YAAY;AAAA;AAAA;AAAA,IAGzD,CAAC,aAAa;AAAA,EAChB;AAEA,SAAO,cAAc,kBAAkB,UAAU,EAAE,OAAO,MAAM,GAAG,QAAQ;AAC7E;AAEA,SAAS,WAA4B;AACnC,QAAM,QAAQ,WAAW,iBAAiB;AAC1C,MAAI,CAAC,OAAO;AACV,UAAM,IAAI;AAAA,MACR;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,OAAyC;AACtE,QAAM,CAAC,OAAO,QAAQ,IAAI,SAAS,MAAM,MAAM,SAAS,CAAC;AAEzD,YAAU,MAAM;AACd,aAAS,MAAM,SAAS,CAAC;AACzB,WAAO,MAAM,UAAU,QAAQ;AAAA,EACjC,GAAG,CAAC,KAAK,CAAC;AAEV,SAAO;AACT;AAiBO,SAAS,gBAAqC;AACnD,QAAM,QAAQ,SAAS;AACvB,QAAM,QAAQ,sBAAsB,KAAK;AAEzC,QAAM,gBAAgB;AAAA,IACpB,CAAC,OAA0C,YACzC,MAAM,cAAc,OAAO,OAAO;AAAA,IACpC,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,UAAU;AAAA,IACd,CAAC,OAA8B,YAA2B,MAAM,QAAQ,OAAO,OAAO;AAAA,IACtF,CAAC,KAAK;AAAA,EACR;AAEA,QAAM,MAAM;AAAA,IACV,CAAC,OAA0C,YAA2B,MAAM,IAAI,OAAO,OAAO;AAAA,IAC9F,CAAC,KAAK;AAAA,EACR;AAEA,SAAO;AAAA,IACL,aAAa,MAAM;AAAA,IACnB,OAAO,MAAM;AAAA,IACb,cAAc,QAAQ,MAAM,YAAY;AAAA,IACxC;AAAA,IACA;AAAA,IACA;AAAA,IACA,gBAAgB,MAAM,eAAe,KAAK,KAAK;AAAA,IAC/C,UAAU,MAAM,SAAS,KAAK,KAAK;AAAA,IACnC,eAAe,MAAM,cAAc,KAAK,KAAK;AAAA,IAC7C,SAAS,MAAM,QAAQ,KAAK,KAAK;AAAA,IACjC,OAAO,MAAM,MAAM,KAAK,KAAK;AAAA,IAC7B;AAAA,EACF;AACF;AAGO,SAAS,iBACd,OACA,SACS;AACT,QAAM,EAAE,eAAe,aAAa,aAAa,IAAI,cAAc;AAEnE,OAAK;AACL,OAAK;AACL,SAAO,cAAc,OAAO,OAAO;AACrC;AAGO,SAAS,WACd,OACA,SACS;AACT,QAAM,EAAE,SAAS,OAAO,aAAa,IAAI,cAAc;AACvD,OAAK;AACL,OAAK;AACL,SAAO,QAAQ,OAAO,OAAO;AAC/B;;;AC9DS;AAnDT,SAAS,eACP,eACA,SACA,OACS;AACT,QAAM,EAAE,YAAY,MAAM,MAAM,UAAU,MAAM,IAAI;AACpD,QAAM,UAAwB,EAAE,KAAK;AAErC,QAAM,eAAe,eAAe;AACpC,QAAM,eAAe,SAAS;AAE9B,MAAI,CAAC,gBAAgB,CAAC,aAAc,QAAO;AAE3C,QAAM,SAAS,eAAe,cAAc,YAAa,OAAO,IAAI;AACpE,QAAM,SAAS,eAAe,QAAQ,MAAO,OAAO,IAAI;AAExD,MAAI,gBAAgB,cAAc;AAChC,WAAO,YAAY,OAAO,UAAU,SAAS,UAAU;AAAA,EACzD;AAEA,SAAO,eAAe,SAAS;AACjC;AAcO,SAAS,IAAI;AAAA,EAClB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA,WAAW;AACb,GAAa;AACX,QAAM,EAAE,eAAe,QAAQ,IAAI,cAAc;AACjD,QAAM,UAAU,eAAe,eAAe,SAAS;AAAA,IACrD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAED,SAAO,gCAAG,oBAAU,WAAW,UAAS;AAC1C;;;AC5DA,SAAS,iBAAiB,yBAAAA,8BAA6B;","names":["createPermissionStore"]}
1
+ {"version":3,"sources":["../../src/react/context.tsx","../../src/react/Can.tsx","../../src/react/ResourceManager.tsx","../../src/react/index.ts"],"sourcesContent":["import {\n createContext,\n createElement,\n useCallback,\n useContext,\n useEffect,\n useMemo,\n useState,\n type ReactNode,\n} from 'react';\nimport {\n createPermissionStore,\n type CheckOptions,\n type PermissionCode,\n type PermissionState,\n type PermissionStore,\n type RoleCode,\n} from '../core';\n\nconst PermissionContext = createContext<PermissionStore | null>(null);\n\nexport interface PermissionProviderProps {\n children: ReactNode;\n /** Pass an existing store to share across trees, or omit to create one. */\n store?: PermissionStore;\n /** Initial state when the provider creates its own store. */\n initialState?: Partial<PermissionState>;\n}\n\nexport function PermissionProvider({\n children,\n store: externalStore,\n initialState,\n}: PermissionProviderProps) {\n const store = useMemo(\n () => externalStore ?? createPermissionStore(initialState),\n // store identity is intentional; initialState only applies on first create\n // eslint-disable-next-line react-hooks/exhaustive-deps\n [externalStore],\n );\n\n return createElement(PermissionContext.Provider, { value: store }, children);\n}\n\nfunction useStore(): PermissionStore {\n const store = useContext(PermissionContext);\n if (!store) {\n throw new Error(\n '[com-angel-authorization/react] usePermission* hooks must be used within <PermissionProvider>.',\n );\n }\n return store;\n}\n\nfunction usePermissionSnapshot(store: PermissionStore): PermissionState {\n const [state, setState] = useState(() => store.getState());\n\n useEffect(() => {\n setState(store.getState());\n return store.subscribe(setState);\n }, [store]);\n\n return state;\n}\n\nexport interface UsePermissionResult {\n permissions: PermissionCode[];\n roles: RoleCode[];\n isSuperAdmin: boolean;\n hasPermission: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n hasRole: (codes: RoleCode | RoleCode[], options?: CheckOptions) => boolean;\n can: (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => boolean;\n setPermissions: (permissions: PermissionCode[]) => void;\n setRoles: (roles: RoleCode[]) => void;\n setSuperAdmin: (isSuperAdmin: boolean) => void;\n hydrate: (payload: Partial<PermissionState>) => void;\n clear: () => void;\n store: PermissionStore;\n}\n\nexport function usePermission(): UsePermissionResult {\n const store = useStore();\n const state = usePermissionSnapshot(store);\n\n const hasPermission = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) =>\n store.hasPermission(codes, options),\n [store],\n );\n\n const hasRole = useCallback(\n (codes: RoleCode | RoleCode[], options?: CheckOptions) => store.hasRole(codes, options),\n [store],\n );\n\n const can = useCallback(\n (codes: PermissionCode | PermissionCode[], options?: CheckOptions) => store.can(codes, options),\n [store],\n );\n\n return {\n permissions: state.permissions,\n roles: state.roles,\n isSuperAdmin: Boolean(state.isSuperAdmin),\n hasPermission,\n hasRole,\n can,\n setPermissions: store.setPermissions.bind(store),\n setRoles: store.setRoles.bind(store),\n setSuperAdmin: store.setSuperAdmin.bind(store),\n hydrate: store.hydrate.bind(store),\n clear: store.clear.bind(store),\n store,\n };\n}\n\n/** Returns whether the current user has the given permission(s). */\nexport function useHasPermission(\n codes: PermissionCode | PermissionCode[],\n options?: CheckOptions,\n): boolean {\n const { hasPermission, permissions, isSuperAdmin } = usePermission();\n // re-compute when permission list / super-admin changes\n void permissions;\n void isSuperAdmin;\n return hasPermission(codes, options);\n}\n\n/** Returns whether the current user has the given role(s). */\nexport function useHasRole(\n codes: RoleCode | RoleCode[],\n options?: CheckOptions,\n): boolean {\n const { hasRole, roles, isSuperAdmin } = usePermission();\n void roles;\n void isSuperAdmin;\n return hasRole(codes, options);\n}\n","import type { ReactNode } from 'react';\nimport type { CheckOptions, PermissionCode, RoleCode } from '../core';\nimport { usePermission } from './context';\n\nexport interface CanProps {\n /** Permission codes to check. */\n permission?: PermissionCode | PermissionCode[];\n /** Role codes to check. */\n role?: RoleCode | RoleCode[];\n /**\n * `any` — pass when at least one code matches (default)\n * `all` — pass only when every code matches\n */\n mode?: CheckOptions['mode'];\n /**\n * How permission and role conditions combine when both are provided.\n * Default: `and` (must satisfy both).\n */\n combine?: 'and' | 'or';\n children: ReactNode;\n /** Fallback when access is denied. */\n fallback?: ReactNode;\n}\n\nfunction evaluateAccess(\n hasPermission: (c: PermissionCode | PermissionCode[], o?: CheckOptions) => boolean,\n hasRole: (c: RoleCode | RoleCode[], o?: CheckOptions) => boolean,\n props: Pick<CanProps, 'permission' | 'role' | 'mode' | 'combine'>,\n): boolean {\n const { permission, role, mode, combine = 'and' } = props;\n const options: CheckOptions = { mode };\n\n const hasPermCheck = permission !== undefined;\n const hasRoleCheck = role !== undefined;\n\n if (!hasPermCheck && !hasRoleCheck) return true;\n\n const permOk = hasPermCheck ? hasPermission(permission!, options) : true;\n const roleOk = hasRoleCheck ? hasRole(role!, options) : true;\n\n if (hasPermCheck && hasRoleCheck) {\n return combine === 'or' ? permOk || roleOk : permOk && roleOk;\n }\n\n return hasPermCheck ? permOk : roleOk;\n}\n\n/**\n * Conditionally render children based on permission / role.\n *\n * @example\n * <Can permission=\"user:edit\">\n * <button>Edit</button>\n * </Can>\n *\n * <Can permission={['user:edit', 'user:delete']} mode=\"all\" fallback={null}>\n * <AdminPanel />\n * </Can>\n */\nexport function Can({\n permission,\n role,\n mode,\n combine,\n children,\n fallback = null,\n}: CanProps) {\n const { hasPermission, hasRole } = usePermission();\n const allowed = evaluateAccess(hasPermission, hasRole, {\n permission,\n role,\n mode,\n combine,\n });\n\n return <>{allowed ? children : fallback}</>;\n}\n","import {\n useCallback,\n useEffect,\n useMemo,\n useState,\n type CSSProperties,\n type FormEvent,\n type ReactNode,\n} from 'react';\nimport {\n RESOURCE_PRIVATE_OPTIONS,\n RESOURCE_STATUS_ENABLED,\n RESOURCE_STATUS_OPTIONS,\n type AuthorizationResource,\n type AuthorizationResourceApi,\n type AuthorizationResourceFormValues,\n type PageDirection,\n} from '../resources';\n\nconst PAGE_SIZE_OPTIONS = ['10', '20', '50', '100'];\n\nconst emptyForm = (): AuthorizationResourceFormValues => ({\n name: '',\n identification: '',\n status: RESOURCE_STATUS_ENABLED,\n private: false,\n description: '',\n});\n\nexport type ResourceManagerProps = {\n api: AuthorizationResourceApi;\n title?: string;\n pageSize?: string;\n /** 自定义顶部右侧操作区 */\n toolbarExtra?: ReactNode;\n};\n\nexport function ResourceManager({\n api,\n title = '权限点管理',\n pageSize: initialPageSize = '20',\n toolbarExtra,\n}: ResourceManagerProps) {\n const [records, setRecords] = useState<AuthorizationResource[]>([]);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState('');\n const [pageSize, setPageSize] = useState(initialPageSize);\n const [pageToken, setPageToken] = useState('');\n const [hasPreviousPage, setHasPreviousPage] = useState(false);\n const [hasNextPage, setHasNextPage] = useState(false);\n\n const [dialogOpen, setDialogOpen] = useState(false);\n const [editing, setEditing] = useState<AuthorizationResource | null>(null);\n const [form, setForm] = useState<AuthorizationResourceFormValues>(emptyForm);\n const [saving, setSaving] = useState(false);\n\n const loadList = useCallback(\n async (direction: PageDirection = 'current', token = pageToken) => {\n setLoading(true);\n setError('');\n try {\n const result = await api.list({\n pagination: {\n pageToken: token,\n pageSize,\n pageDirection: direction,\n },\n });\n setRecords(result.records);\n setPageToken(result.pageToken);\n setHasPreviousPage(result.hasPreviousPage);\n setHasNextPage(result.hasNextPage);\n } catch (err) {\n setError(err instanceof Error ? err.message : '加载失败');\n } finally {\n setLoading(false);\n }\n },\n [api, pageSize, pageToken],\n );\n\n useEffect(() => {\n void loadList('current', '');\n // 仅 pageSize / api 变化时重置首页\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [api, pageSize]);\n\n const openCreate = () => {\n setEditing(null);\n setForm(emptyForm());\n setDialogOpen(true);\n };\n\n const openEdit = (row: AuthorizationResource) => {\n setEditing(row);\n setForm({\n name: row.name,\n identification: row.identification,\n status: row.status,\n private: row.private,\n description: row.description,\n });\n setDialogOpen(true);\n };\n\n const closeDialog = () => {\n if (saving) return;\n setDialogOpen(false);\n };\n\n const handleSubmit = async (event: FormEvent) => {\n event.preventDefault();\n if (!form.name.trim()) {\n setError('请填写权限名称');\n return;\n }\n if (!form.identification.trim()) {\n setError('请填写接口标识');\n return;\n }\n\n setSaving(true);\n setError('');\n try {\n if (editing) {\n await api.update(editing.resourceId, form);\n } else {\n await api.create(form);\n }\n setDialogOpen(false);\n await loadList('current', '');\n } catch (err) {\n setError(err instanceof Error ? err.message : '保存失败');\n } finally {\n setSaving(false);\n }\n };\n\n const handleDelete = async (row: AuthorizationResource) => {\n if (!window.confirm(`确认删除权限点「${row.name}」?`)) return;\n setError('');\n try {\n await api.remove(row.resourceId);\n await loadList('current', '');\n } catch (err) {\n setError(err instanceof Error ? err.message : '删除失败');\n }\n };\n\n const statusLabel = useMemo(\n () =>\n Object.fromEntries(RESOURCE_STATUS_OPTIONS.map((o) => [o.value, o.label])) as Record<\n number,\n string\n >,\n [],\n );\n\n return (\n <div style={styles.root}>\n <div style={styles.toolbar}>\n <h2 style={styles.title}>{title}</h2>\n <div style={styles.toolbarRight}>\n {toolbarExtra}\n <button type=\"button\" style={styles.primaryBtn} onClick={openCreate}>\n 新增\n </button>\n </div>\n </div>\n\n {error ? <div style={styles.error}>{error}</div> : null}\n\n <div style={styles.tableWrap}>\n <table style={styles.table}>\n <thead>\n <tr>\n <th style={styles.th}>权限名称</th>\n <th style={styles.th}>接口标识</th>\n <th style={styles.th}>描述</th>\n <th style={{ ...styles.th, width: 90 }}>状态</th>\n <th style={{ ...styles.th, width: 140 }}>操作</th>\n </tr>\n </thead>\n <tbody>\n {loading ? (\n <tr>\n <td colSpan={5} style={styles.empty}>\n 加载中…\n </td>\n </tr>\n ) : records.length === 0 ? (\n <tr>\n <td colSpan={5} style={styles.empty}>\n 暂无数据\n </td>\n </tr>\n ) : (\n records.map((row) => (\n <tr key={row.resourceId}>\n <td style={styles.td}>{row.name}</td>\n <td style={styles.td}>\n <code style={styles.code}>{row.identification}</code>\n </td>\n <td style={styles.td}>{row.description || '—'}</td>\n <td style={styles.td}>\n <span\n style={{\n ...styles.badge,\n background:\n row.status === RESOURCE_STATUS_ENABLED ? '#e8f7ef' : '#f4f4f5',\n color: row.status === RESOURCE_STATUS_ENABLED ? '#067647' : '#667085',\n }}\n >\n {statusLabel[row.status] ?? row.status}\n </span>\n </td>\n <td style={styles.td}>\n <button type=\"button\" style={styles.linkBtn} onClick={() => openEdit(row)}>\n 编辑\n </button>\n <button\n type=\"button\"\n style={{ ...styles.linkBtn, color: '#d92d20' }}\n onClick={() => void handleDelete(row)}\n >\n 删除\n </button>\n </td>\n </tr>\n ))\n )}\n </tbody>\n </table>\n </div>\n\n <div style={styles.pagination}>\n <label style={styles.pageSize}>\n 每页\n <select\n value={pageSize}\n onChange={(e) => {\n setPageToken('');\n setPageSize(e.target.value);\n }}\n style={styles.select}\n >\n {PAGE_SIZE_OPTIONS.map((size) => (\n <option key={size} value={size}>\n {size}\n </option>\n ))}\n </select>\n </label>\n <div style={styles.pageBtns}>\n <button\n type=\"button\"\n style={styles.secondaryBtn}\n disabled={!hasPreviousPage || loading}\n onClick={() => void loadList('previous')}\n >\n 上一页\n </button>\n <button\n type=\"button\"\n style={styles.secondaryBtn}\n disabled={!hasNextPage || loading}\n onClick={() => void loadList('next')}\n >\n 下一页\n </button>\n </div>\n </div>\n\n {dialogOpen ? (\n <div style={styles.mask} onClick={closeDialog}>\n <div\n style={styles.dialog}\n onClick={(e) => e.stopPropagation()}\n role=\"dialog\"\n aria-modal=\"true\"\n >\n <div style={styles.dialogHeader}>\n <h3 style={styles.dialogTitle}>{editing ? '编辑权限点' : '新增权限点'}</h3>\n <button type=\"button\" style={styles.iconBtn} onClick={closeDialog} aria-label=\"关闭\">\n ×\n </button>\n </div>\n <form style={styles.form} onSubmit={(e) => void handleSubmit(e)}>\n <label style={styles.field}>\n <span style={styles.label}>权限名称</span>\n <input\n style={styles.input}\n value={form.name}\n onChange={(e) => setForm((prev) => ({ ...prev, name: e.target.value }))}\n placeholder=\"请输入权限名称\"\n required\n />\n </label>\n <label style={styles.field}>\n <span style={styles.label}>接口标识</span>\n <input\n style={styles.input}\n value={form.identification}\n onChange={(e) =>\n setForm((prev) => ({ ...prev, identification: e.target.value }))\n }\n placeholder=\"如 user:list\"\n required\n />\n </label>\n <label style={styles.field}>\n <span style={styles.label}>状态</span>\n <select\n style={styles.input}\n value={form.status}\n onChange={(e) =>\n setForm((prev) => ({\n ...prev,\n status: Number(e.target.value) as 0 | 1,\n }))\n }\n >\n {RESOURCE_STATUS_OPTIONS.map((opt) => (\n <option key={opt.value} value={opt.value}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n <label style={styles.field}>\n <span style={styles.label}>私有资源</span>\n <select\n style={styles.input}\n value={form.private ? '1' : '0'}\n onChange={(e) =>\n setForm((prev) => ({ ...prev, private: e.target.value === '1' }))\n }\n >\n {RESOURCE_PRIVATE_OPTIONS.map((opt) => (\n <option key={String(opt.value)} value={opt.value ? '1' : '0'}>\n {opt.label}\n </option>\n ))}\n </select>\n </label>\n <label style={styles.field}>\n <span style={styles.label}>描述</span>\n <textarea\n style={{ ...styles.input, minHeight: 88, resize: 'vertical' }}\n value={form.description}\n onChange={(e) =>\n setForm((prev) => ({ ...prev, description: e.target.value }))\n }\n placeholder=\"请输入描述\"\n />\n </label>\n <div style={styles.dialogFooter}>\n <button type=\"button\" style={styles.secondaryBtn} onClick={closeDialog}>\n 取消\n </button>\n <button type=\"submit\" style={styles.primaryBtn} disabled={saving}>\n {saving ? '保存中…' : '保存'}\n </button>\n </div>\n </form>\n </div>\n </div>\n ) : null}\n </div>\n );\n}\n\nconst styles: Record<string, CSSProperties> = {\n root: {\n display: 'flex',\n flexDirection: 'column',\n gap: 16,\n padding: 16,\n color: '#101828',\n fontFamily:\n '\"PingFang SC\", \"Microsoft YaHei\", -apple-system, BlinkMacSystemFont, sans-serif',\n },\n toolbar: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n },\n title: { margin: 0, fontSize: 18, fontWeight: 600 },\n toolbarRight: { display: 'flex', alignItems: 'center', gap: 8 },\n error: {\n padding: '10px 12px',\n borderRadius: 8,\n background: '#fef3f2',\n color: '#b42318',\n fontSize: 13,\n },\n tableWrap: {\n overflow: 'auto',\n border: '1px solid #eaecf0',\n borderRadius: 10,\n background: '#fff',\n },\n table: { width: '100%', borderCollapse: 'collapse', minWidth: 720 },\n th: {\n textAlign: 'left',\n padding: '12px 14px',\n fontSize: 13,\n fontWeight: 600,\n color: '#475467',\n background: '#f9fafb',\n borderBottom: '1px solid #eaecf0',\n },\n td: {\n padding: '12px 14px',\n fontSize: 14,\n borderBottom: '1px solid #f2f4f7',\n verticalAlign: 'middle',\n },\n empty: {\n padding: 28,\n textAlign: 'center',\n color: '#98a2b3',\n fontSize: 14,\n },\n code: {\n fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace',\n fontSize: 13,\n background: '#f2f4f7',\n padding: '2px 6px',\n borderRadius: 4,\n },\n badge: {\n display: 'inline-block',\n padding: '2px 8px',\n borderRadius: 999,\n fontSize: 12,\n fontWeight: 500,\n },\n linkBtn: {\n border: 'none',\n background: 'transparent',\n color: '#049BAD',\n cursor: 'pointer',\n padding: '0 8px 0 0',\n fontSize: 13,\n },\n pagination: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n gap: 12,\n },\n pageSize: { display: 'flex', alignItems: 'center', gap: 8, fontSize: 13, color: '#475467' },\n pageBtns: { display: 'flex', gap: 8 },\n primaryBtn: {\n border: 'none',\n background: '#049BAD',\n color: '#fff',\n borderRadius: 8,\n padding: '8px 14px',\n cursor: 'pointer',\n fontSize: 14,\n },\n secondaryBtn: {\n border: '1px solid #d0d5dd',\n background: '#fff',\n color: '#344054',\n borderRadius: 8,\n padding: '8px 14px',\n cursor: 'pointer',\n fontSize: 14,\n },\n select: {\n border: '1px solid #d0d5dd',\n borderRadius: 6,\n padding: '4px 8px',\n fontSize: 13,\n },\n mask: {\n position: 'fixed',\n inset: 0,\n background: 'rgba(16, 24, 40, 0.45)',\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'center',\n zIndex: 1000,\n padding: 16,\n },\n dialog: {\n width: '100%',\n maxWidth: 480,\n background: '#fff',\n borderRadius: 12,\n boxShadow: '0 20px 40px rgba(16,24,40,0.18)',\n },\n dialogHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '14px 16px',\n borderBottom: '1px solid #eaecf0',\n },\n dialogTitle: { margin: 0, fontSize: 16, fontWeight: 600 },\n iconBtn: {\n border: 'none',\n background: 'transparent',\n fontSize: 22,\n lineHeight: 1,\n cursor: 'pointer',\n color: '#667085',\n },\n form: { display: 'flex', flexDirection: 'column', gap: 12, padding: 16 },\n field: { display: 'flex', flexDirection: 'column', gap: 6 },\n label: { fontSize: 13, color: '#344054', fontWeight: 500 },\n input: {\n border: '1px solid #d0d5dd',\n borderRadius: 8,\n padding: '8px 10px',\n fontSize: 14,\n outline: 'none',\n },\n dialogFooter: {\n display: 'flex',\n justifyContent: 'flex-end',\n gap: 8,\n paddingTop: 4,\n },\n};\n","export { PermissionProvider, usePermission, useHasPermission, useHasRole } from './context';\nexport type { PermissionProviderProps, UsePermissionResult } from './context';\n\nexport { Can } from './Can';\nexport type { CanProps } from './Can';\n\nexport { ResourceManager } from './ResourceManager';\nexport type { ResourceManagerProps } from './ResourceManager';\n\nexport type {\n CheckOptions,\n MatchMode,\n PermissionChecker,\n PermissionCode,\n PermissionListener,\n PermissionState,\n RoleCode,\n} from '../core';\n\nexport { PermissionStore, createPermissionStore } from '../core';\n\nexport { getAppClientId, getDeviceWorkerId, snowyflake } from '../utils/snowflake';\n\nexport type {\n AuthorizationResource,\n AuthorizationResourceApi,\n AuthorizationResourceFormValues,\n AuthorizationResourceListResult,\n CreateAuthorizationResourceBody,\n CreateDefaultResourceRequestOptions,\n FetchAuthorizationResourcesParams,\n HttpMethod,\n ListPaginationParams,\n ListPaginationResult,\n PageDirection,\n ResourceHttpRequest,\n ResourceRequestOptions,\n ResourceStatus,\n UpdateAuthorizationResourceBody,\n} from '../resources';\n\nexport {\n RESOURCE_PRIVATE_OPTIONS,\n RESOURCE_STATUS_DISABLED,\n RESOURCE_STATUS_ENABLED,\n RESOURCE_STATUS_OPTIONS,\n RESOURCE_TYPE_API,\n appendQueryParam,\n buildCreateBody,\n buildUpdateBody,\n createAuthorizationResourceApi,\n createDefaultResourceRequest,\n extractPagination,\n extractRecords,\n mapAuthorizationResource,\n} from '../resources';\n"],"mappings":"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","names":["useCallback","useEffect","useMemo","useState","jsx","createPermissionStore","RESOURCE_PRIVATE_OPTIONS","RESOURCE_STATUS_ENABLED","RESOURCE_STATUS_OPTIONS"]}