@nocobase/app-plugin-api-keys 0.0.0-stage → 1.0.0-beta.13
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 +418 -0
- package/README.md +165 -2
- package/dist/client/api-keys-client.d.ts +19 -0
- package/dist/client/api-keys-client.d.ts.map +1 -0
- package/dist/client/api-keys-client.js +7 -0
- package/dist/client/api-keys-client.js.map +1 -0
- package/dist/client/components/page-container.d.ts +4 -0
- package/dist/client/components/page-container.d.ts.map +1 -0
- package/dist/client/components/page-container.js +6 -0
- package/dist/client/components/page-container.js.map +1 -0
- package/dist/client/components/page-header.d.ts +8 -0
- package/dist/client/components/page-header.d.ts.map +1 -0
- package/dist/client/components/page-header.js +5 -0
- package/dist/client/components/page-header.js.map +1 -0
- package/dist/client/components/ui/alert-dialog.d.ts +19 -0
- package/dist/client/components/ui/alert-dialog.d.ts.map +1 -0
- package/dist/client/components/ui/alert-dialog.js +42 -0
- package/dist/client/components/ui/alert-dialog.js.map +1 -0
- package/dist/client/components/ui/badge.d.ts +6 -0
- package/dist/client/components/ui/badge.d.ts.map +1 -0
- package/dist/client/components/ui/badge.js +8 -0
- package/dist/client/components/ui/badge.js.map +1 -0
- package/dist/client/components/ui/button.d.ts +8 -0
- package/dist/client/components/ui/button.d.ts.map +1 -0
- package/dist/client/components/ui/button.js +27 -0
- package/dist/client/components/ui/button.js.map +1 -0
- package/dist/client/components/ui/dialog.d.ts +9 -0
- package/dist/client/components/ui/dialog.d.ts.map +1 -0
- package/dist/client/components/ui/dialog.js +29 -0
- package/dist/client/components/ui/dialog.js.map +1 -0
- package/dist/client/components/ui/input.d.ts +4 -0
- package/dist/client/components/ui/input.d.ts.map +1 -0
- package/dist/client/components/ui/input.js +8 -0
- package/dist/client/components/ui/input.js.map +1 -0
- package/dist/client/components/ui/label.d.ts +3 -0
- package/dist/client/components/ui/label.d.ts.map +1 -0
- package/dist/client/components/ui/label.js +6 -0
- package/dist/client/components/ui/label.js.map +1 -0
- package/dist/client/components/ui/select.d.ts +8 -0
- package/dist/client/components/ui/select.d.ts.map +1 -0
- package/dist/client/components/ui/select.js +19 -0
- package/dist/client/components/ui/select.js.map +1 -0
- package/dist/client/components/ui/spinner.d.ts +4 -0
- package/dist/client/components/ui/spinner.d.ts.map +1 -0
- package/dist/client/components/ui/spinner.js +11 -0
- package/dist/client/components/ui/spinner.js.map +1 -0
- package/dist/client/components/ui/table.d.ts +8 -0
- package/dist/client/components/ui/table.d.ts.map +1 -0
- package/dist/client/components/ui/table.js +21 -0
- package/dist/client/components/ui/table.js.map +1 -0
- package/dist/client/expiry.d.ts +23 -0
- package/dist/client/expiry.d.ts.map +1 -0
- package/dist/client/expiry.js +40 -0
- package/dist/client/expiry.js.map +1 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.d.ts.map +1 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/lib/utils.d.ts +2 -0
- package/dist/client/lib/utils.d.ts.map +1 -0
- package/dist/client/lib/utils.js +2 -0
- package/dist/client/lib/utils.js.map +1 -0
- package/dist/client/locales/en-US.d.ts +71 -0
- package/dist/client/locales/en-US.d.ts.map +1 -0
- package/dist/client/locales/en-US.js +62 -0
- package/dist/client/locales/en-US.js.map +1 -0
- package/dist/client/locales/index.d.ts +4 -0
- package/dist/client/locales/index.d.ts.map +1 -0
- package/dist/client/locales/index.js +7 -0
- package/dist/client/locales/index.js.map +1 -0
- package/dist/client/locales/zh-CN.d.ts +4 -0
- package/dist/client/locales/zh-CN.d.ts.map +1 -0
- package/dist/client/locales/zh-CN.js +62 -0
- package/dist/client/locales/zh-CN.js.map +1 -0
- package/dist/client/pages/api-keys-page.d.ts +3 -0
- package/dist/client/pages/api-keys-page.d.ts.map +1 -0
- package/dist/client/pages/api-keys-page.js +161 -0
- package/dist/client/pages/api-keys-page.js.map +1 -0
- package/dist/client/plugin.d.ts +9 -0
- package/dist/client/plugin.d.ts.map +1 -0
- package/dist/client/plugin.js +10 -0
- package/dist/client/plugin.js.map +1 -0
- package/dist/client/routes.d.ts +22 -0
- package/dist/client/routes.d.ts.map +1 -0
- package/dist/client/routes.js +42 -0
- package/dist/client/routes.js.map +1 -0
- package/dist/database/migrations/.manifest.json +9 -0
- package/dist/database/migrations/202609150001_create_api_key_table.js +58 -0
- package/dist/database/migrations/202609150001_create_api_key_table.js.map +1 -0
- package/dist/server/api-docs.d.ts +24 -0
- package/dist/server/api-docs.d.ts.map +1 -0
- package/dist/server/api-docs.js +73 -0
- package/dist/server/api-docs.js.map +1 -0
- package/dist/server/api-keys.d.ts +52 -0
- package/dist/server/api-keys.d.ts.map +1 -0
- package/dist/server/api-keys.js +199 -0
- package/dist/server/api-keys.js.map +1 -0
- package/dist/server/index.d.ts +23 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +22 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/key-sessions.d.ts +35 -0
- package/dist/server/key-sessions.d.ts.map +1 -0
- package/dist/server/key-sessions.js +50 -0
- package/dist/server/key-sessions.js.map +1 -0
- package/dist/server/plugin.d.ts +4 -0
- package/dist/server/plugin.d.ts.map +1 -0
- package/dist/server/plugin.js +15 -0
- package/dist/server/plugin.js.map +1 -0
- package/dist/server/providers/index.d.ts +19 -0
- package/dist/server/providers/index.d.ts.map +1 -0
- package/dist/server/providers/index.js +72 -0
- package/dist/server/providers/index.js.map +1 -0
- package/dist/server/routes/errors.d.ts +8 -0
- package/dist/server/routes/errors.d.ts.map +1 -0
- package/dist/server/routes/errors.js +48 -0
- package/dist/server/routes/errors.js.map +1 -0
- package/dist/server/routes/index.d.ts +10 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/routes/index.js +177 -0
- package/dist/server/routes/index.js.map +1 -0
- package/dist/server/routes/schemas.d.ts +25 -0
- package/dist/server/routes/schemas.d.ts.map +1 -0
- package/dist/server/routes/schemas.js +127 -0
- package/dist/server/routes/schemas.js.map +1 -0
- package/dist/server/scoped-keys.d.ts +116 -0
- package/dist/server/scoped-keys.d.ts.map +1 -0
- package/dist/server/scoped-keys.js +451 -0
- package/dist/server/scoped-keys.js.map +1 -0
- package/dist/server/scopes.d.ts +70 -0
- package/dist/server/scopes.d.ts.map +1 -0
- package/dist/server/scopes.js +165 -0
- package/dist/server/scopes.js.map +1 -0
- package/dist/server/service.d.ts +28 -0
- package/dist/server/service.d.ts.map +1 -0
- package/dist/server/service.js +69 -0
- package/dist/server/service.js.map +1 -0
- package/dist/server/tokens.d.ts +6 -0
- package/dist/server/tokens.d.ts.map +1 -0
- package/dist/server/tokens.js +5 -0
- package/dist/server/tokens.js.map +1 -0
- package/dist/shared/scopes.d.ts +160 -0
- package/dist/shared/scopes.d.ts.map +1 -0
- package/dist/shared/scopes.js +83 -0
- package/dist/shared/scopes.js.map +1 -0
- package/package.json +91 -3
- package/skills/nocobase-app-plugin-api-keys/SKILL.md +166 -0
package/README.md
CHANGED
|
@@ -1,3 +1,166 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @nocobase/app-plugin-api-keys
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
API key authentication for NocoBase applications, built on Better Auth.
|
|
4
|
+
|
|
5
|
+
A key authenticates as the user who created it. `Auth.getSession()` resolves the `x-api-key` header the same way it resolves a session cookie, so `auth.required()`, the route guards, and `@nocobase/app-plugin-authorization` all see the owning user and exactly the roles that user holds. Nothing in an application has to know a request arrived by key rather than by cookie.
|
|
6
|
+
|
|
7
|
+
Keys are self-service: each signed-in user creates and revokes their own under `/settings/api-keys`.
|
|
8
|
+
|
|
9
|
+
## What this package is
|
|
10
|
+
|
|
11
|
+
Better Auth's [API Key plugin](https://www.better-auth.com/docs/plugins/api-key), plus the parts an application needs around it:
|
|
12
|
+
|
|
13
|
+
- the `apikey` table migration;
|
|
14
|
+
- the Settings page and its locales;
|
|
15
|
+
- `apiKey` and `apiKeyClient`, carrying Better Auth's own names and options.
|
|
16
|
+
|
|
17
|
+
`apiKey` is wrapped only to supply three defaults, all of them overridable; everything else is Better Auth's behavior and its documentation applies unchanged. They come from this package rather than from a dependency each application installs because the migration here has to match the schema that version of `@better-auth/api-key` declares; a test asserts the table carries a column for every field the plugin declares.
|
|
18
|
+
|
|
19
|
+
## Installing it
|
|
20
|
+
|
|
21
|
+
```ts
|
|
22
|
+
// server/plugins.ts — migrations for the apikey table
|
|
23
|
+
import apiKeys from '@nocobase/app-plugin-api-keys/server';
|
|
24
|
+
|
|
25
|
+
// server/config/auth.ts — the Better Auth plugin itself
|
|
26
|
+
import { apiKey } from '@nocobase/app-plugin-api-keys/server';
|
|
27
|
+
|
|
28
|
+
export default defineAppConfig((_runtime) => ({
|
|
29
|
+
plugins: [username({ displayUsername: false }), apiKey()],
|
|
30
|
+
}));
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
// client/plugins.ts — the management page
|
|
35
|
+
import apiKeys from '@nocobase/app-plugin-api-keys/client';
|
|
36
|
+
apiKeys({ path: '/api-keys' });
|
|
37
|
+
|
|
38
|
+
// client/config/auth.ts — so authClient.apiKey.* reaches the endpoints
|
|
39
|
+
import { apiKeyClient } from '@nocobase/app-plugin-api-keys/client';
|
|
40
|
+
|
|
41
|
+
export default defineAppConfig((_runtime) => ({
|
|
42
|
+
plugins: [usernameClient({ displayUsername: false }), apiKeyClient()],
|
|
43
|
+
}));
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Then grant `page:api-keys/access` to the roles that may manage keys — normally all authenticated users, since every endpoint acts only on the caller's own keys — and run `pnpm nocobase db apply`.
|
|
47
|
+
|
|
48
|
+
Registering the server plugin without `apiKey()` creates the table and mounts no endpoints; registering `apiKey()` without the server plugin mounts endpoints against a table that does not exist.
|
|
49
|
+
|
|
50
|
+
## The three defaults
|
|
51
|
+
|
|
52
|
+
| Option | Better Auth | Here | Why |
|
|
53
|
+
| ------------------------- | ----------------------------------- | ------- | ----------------------------------------------------------------------------------------------------------------------- |
|
|
54
|
+
| `enableSessionForAPIKeys` | `false` | `true` | Without it a key authenticates nothing: the page still issues keys, and every request carrying one answers 401 |
|
|
55
|
+
| `rateLimit.enabled` | `true`, 10 requests per key per day | `false` | That is a quota for issuing keys rather than for using them, and it silently breaks the first integration anyone writes |
|
|
56
|
+
| `requireName` | `false` | `true` | The management page identifies a key by its name, and a key listed as "unnamed" cannot be revoked with any confidence |
|
|
57
|
+
|
|
58
|
+
All three are overridable. `apiKey({ rateLimit: { enabled: true, maxRequests: 1000, timeWindow: 60_000 } })` sets a quota, and passing all three back reproduces Better Auth's own behaviour exactly.
|
|
59
|
+
|
|
60
|
+
## Using a key
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
curl -H 'x-api-key: <key>' https://example.com/api/orders
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Reading the API document with a key
|
|
67
|
+
|
|
68
|
+
A valid key may read the application's OpenAPI document and its Swagger UI, exactly as a signed-in session may: `curl -H 'x-api-key: <key>' https://example.com/api/swagger` returns the JSON document, and `/api/swagger/docs` the page. The key is checked the way every other request checks it, so an unknown, expired or disabled key, or one whose owner is disabled, gets `401` with `error.reason` `API_DOCS_UNAUTHENTICATED`, and reading the document extends no session. The document lists this plugin's endpoints under `/api/auth/api-key/...` with the rest of Better Auth's, tagged `Authentication`. A configuration with a `customAPIKeyGetter` is not consulted by this check, because the getter needs a Better Auth endpoint context.
|
|
69
|
+
|
|
70
|
+
## What a key can do
|
|
71
|
+
|
|
72
|
+
A key is its owner. Beyond the application's own routes, it reaches the Better Auth endpoints Better Auth lets a session reach — verified against `@better-auth/api-key` 1.7.1 with only an `x-api-key` header:
|
|
73
|
+
|
|
74
|
+
| Endpoint | |
|
|
75
|
+
| ------------------------------------------------------------------ | ----------------------------------------------------------------------- |
|
|
76
|
+
| `/api-key/*` (create, list, update, delete) | 403 `API_KEY_SESSION_FORBIDDEN` — managing keys takes a sign-in |
|
|
77
|
+
| `POST /update-user` | reachable — profile fields |
|
|
78
|
+
| `GET /list-sessions` | reachable — returns session rows including the unsigned session `token` |
|
|
79
|
+
| `POST /sign-out` | reachable |
|
|
80
|
+
| `POST /delete-user`, `POST /change-email`, `POST /revoke-sessions` | 401 |
|
|
81
|
+
| `POST /change-password` | requires `currentPassword` |
|
|
82
|
+
|
|
83
|
+
**No key manages keys.** Every `/api-key/*` endpoint refuses a request made with a key, scoped or not, so a leaked key cannot mint its own successors or revoke the evidence; only a signed-in session creates, updates or deletes keys. Routes of the application that manage keys apply the same rule with `requireSignInSession()` after `auth.required()`.
|
|
84
|
+
|
|
85
|
+
One consequence of an unscoped key reaching the rest is worth planning for. **`/list-sessions` discloses the session token.** It is the unsigned half of the session cookie, which is `token.signature`; replaying it alone does not authenticate, because the HMAC is computed with the auth secret. It becomes a working session takeover only if that secret also leaks or a deployment turns cookie signing off.
|
|
86
|
+
|
|
87
|
+
An application that wants it closed gives the key a scope, or adds a Better Auth `before` hook of its own.
|
|
88
|
+
|
|
89
|
+
A rejected key — expired, revoked, or wrong — is answered by a guarded `/api` route with Better Auth's own status in the standard error body, its code as `error.reason` and `authentication` as `error.domain`, so the caller can tell why: `401 KEY_EXPIRED`, `401 KEY_NOT_FOUND`, `429 USAGE_EXCEEDED`. Branch on `error.reason`, never on `message`. `Auth.getSession()` throws Better Auth's `APIError` for a refused key, exactly as Better Auth itself does, and a caller that only asks who is signed in catches it. A disabled user's keys stop working immediately, because `Auth.getSession()` re-reads `user.disabledAt` on every request.
|
|
90
|
+
|
|
91
|
+
## Scoped keys
|
|
92
|
+
|
|
93
|
+
A key may carry a scope, as a GitHub fine-grained token does. Its effective permission is its owner's current permission intersected with the scope: the scope never grants anything, and an owner who loses a permission takes it from every key at once. A key without a scope behaves exactly as described above.
|
|
94
|
+
|
|
95
|
+
The scope is a set of permission groups, each at a level — read, write, or admin, each including the ones before it — and, where a group offers it, limited to some records of a business ("only selected Apps"). Plugins declare their groups as plain data (`KeyScopeGroupDeclaration`, `KeyScopePresetDeclaration` from `@nocobase/app-plugin-api-keys/shared/scopes`, written as literals so the plugin does not depend on this package); the application assembles them, because only it knows every plugin:
|
|
96
|
+
|
|
97
|
+
```ts
|
|
98
|
+
const scopes = container.resolve(apiKeyScopesToken);
|
|
99
|
+
scopes.mapAccess((ref) => /* page, settings or business access → { resource, action } */);
|
|
100
|
+
scopes.groups.add(RELEASES_KEY_SCOPE_GROUPS[0], releasesKeyScopeObjects(services));
|
|
101
|
+
scopes.presets.add(CI_DEPLOY_PRESET);
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
A scope is stored in Better Auth's `permissions` column, which Better Auth refuses to take from a client on create or update (`SERVER_ONLY_PROPERTY`), so a key's holder cannot widen it: `{ "$v": ["1"], "releases.apps": ["read", "write"], "releases.apps@": ["app-1"] }`. `/api/apiKeys` offers no way to change a person's key's scope; create another. An application that manages keys of its own (an organization's keys, say) may change one with `ScopedApiKeys.setScope`, deciding itself who may and what they may give. A group the application no longer registers grants nothing, so removing one only narrows the keys that named it.
|
|
105
|
+
|
|
106
|
+
What enforces a scope on each request:
|
|
107
|
+
|
|
108
|
+
- Better Auth turns the key into its owner's session, as for any key. This plugin's provider then recognizes the key behind the session (its id and token), reads its scope once per request, and adds it to the authorization identity as `keyScope` (`authz.use`). `authz.can`, `require`, `authorize` and the permissions snapshot deny anything outside it with `KEY_SCOPE`.
|
|
109
|
+
- `auth.required()` refuses a scoped key with 403 `SCOPED_KEY_FORBIDDEN` unless the route opts in with `auth.required({ scopedKeys: true })`. Opt in only where every operation is authorized through `authz`, or where the code narrows by `identity.keyScope` itself; anything that derives permissions on its own (from `permissionSets.getEffective`, say) must intersect with `keyScope` or it widens the key back to its owner.
|
|
110
|
+
- A scoped key reaches no Better Auth account endpoint but `/get-session`: it cannot mint or list keys, change the profile, list sessions or sign out.
|
|
111
|
+
- Record selections are enforced only by the plugin that owns the records, through `keyScope.objects(business)`. An empty selection reaches none of them: the key holds the group's actions, so the commands and routes that need them are offered, while every record the plugin checks is refused.
|
|
112
|
+
|
|
113
|
+
A service account's key is treated as scoped even without a scope: `required()` refuses it unless the route opts in, it reaches no account endpoint, and its identity carries a `keyScope` that narrows nothing (`permissions: null`), so plugins can tell a key from a person. Disabling the account stops all its keys immediately.
|
|
114
|
+
|
|
115
|
+
`apiKeys.maxScopedKeyDays` in the application's configuration caps how long a scoped key lives; unset, "never expires" stays available. The editor proposes 90 days.
|
|
116
|
+
|
|
117
|
+
### Server API
|
|
118
|
+
|
|
119
|
+
| Export | What it is |
|
|
120
|
+
| ---------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
121
|
+
| `apiKeyScopesToken` | The registry: `groups.add`, `presets.add`, `mapAccess`, `validate`, `compile` |
|
|
122
|
+
| `scopedApiKeysToken` | `ScopedApiKeys`: `scopeOptions`, `scopeObjects`, `list`, `get`, `check`, `create`, `issueChecked`, `setScope`, `update`, `rotate`, `revoke`, `revokeAll`, `resolve`, `setOwnKeyPolicy` |
|
|
123
|
+
| `ApiKeyScopeError` | A refused scope, 400 with a stable code |
|
|
124
|
+
| `encodeKeyScope`, `decodeKeyScope` | The storage format |
|
|
125
|
+
|
|
126
|
+
`ScopedApiKeys` acts on whichever user it is told; the caller decides who may manage whose keys. An application builds its own key pages and a service account's keys on it.
|
|
127
|
+
|
|
128
|
+
- `check(input, identity)` validates what `create` would issue — name, description, scope, the records it picks (each must be one `identity` may see) and expiry — without issuing anything, so a caller can refuse before it creates whatever the key belongs to; `issueChecked(userId, checked)` then issues it.
|
|
129
|
+
- `rotate(userId, keyId)` gives a key a new secret in place: the same id, name, description, scope and owner, with the expiry renewed for the lifetime the key had. The old secret stops at once. Better Auth generates and hashes the new value, so its key options apply.
|
|
130
|
+
- `setScope(userId, keyId, scope, identity)` replaces a scoped key's scope; `update(userId, keyId, { name?, description? })` renames it.
|
|
131
|
+
- `setOwnKeyPolicy(policy)` says who may create (and rotate) keys of their own: `(userId) => Promise<boolean>`. Without one everyone may. With one, `POST /api/apiKeys`, its rotation and Better Auth's own `/api-key/create` from a sign-in answer 403 `API_KEY_CREATION_FORBIDDEN` to anyone the policy refuses, while listing and revoking stay open. The plugin's provider connects the Better Auth hook at boot (`connectOwnKeyPolicy`).
|
|
132
|
+
|
|
133
|
+
### HTTP API
|
|
134
|
+
|
|
135
|
+
`/api/apiKeys`, for the signed-in person's own keys (a scoped key or a service account is refused with 403 `SCOPED_KEY_FORBIDDEN`, any other key with 403 `API_KEY_SESSION_FORBIDDEN`). Failures answer in the standard error body with domain `apiKeys` and the codes above as `reason`; an invalid body is 400 `INVALID_INPUT` naming the field, and an unknown field is rejected.
|
|
136
|
+
|
|
137
|
+
| Request | Answer |
|
|
138
|
+
| ------------------------------------------------------- | -------------------------------------------------------------------------------------------------------- |
|
|
139
|
+
| `GET /scopeOptions` | `{ data }`, `KeyScopeOptions`: the groups with what the caller holds today, presets, expiry, `mayCreate` |
|
|
140
|
+
| `GET /scopeObjects/:group?q=&id=` | `{ data, meta: { total } }`: the records the caller may choose for a group; `id` may repeat |
|
|
141
|
+
| `GET /` | `{ data, meta: { total } }`: the caller's keys, with scope and last use, never a secret |
|
|
142
|
+
| `POST /` `{ name, description?, expiresInDays, scope }` | 201 `{ data: { key, secret } }`, the secret shown once |
|
|
143
|
+
| `POST /:keyId/rotate` | `{ data: { key, secret } }`: same id, name, scope and lifetime; the old secret stops at once |
|
|
144
|
+
| `DELETE /:keyId` | 204 |
|
|
145
|
+
|
|
146
|
+
`toApiKeysApiError(error)` turns `ApiKeyScopeError` and `ApiKeyRequestError` into that body's `ApiError`, for an application's own key routes: `router.onError((error, context) => apiErrorHandler(toApiKeysApiError(error), context))`.
|
|
147
|
+
|
|
148
|
+
The Settings page under `/settings/api-keys` predates scopes and does not offer them; an application that offers scoped keys builds its own page on this API.
|
|
149
|
+
|
|
150
|
+
## Verification
|
|
151
|
+
|
|
152
|
+
```bash
|
|
153
|
+
pnpm --filter @nocobase/app-plugin-api-keys check
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
## Server extensions
|
|
157
|
+
|
|
158
|
+
Pass an array to `apiKey()` to configure multiple key classes with unique `configId` values. Each entry receives the usual overridable NocoBase defaults. Set `enableSessionForAPIKeys: false` for keys that an application verifies explicitly instead of resolving into the owner’s Session.
|
|
159
|
+
|
|
160
|
+
`ApiKeyService` from the server entry binds trusted `create`, `get`, `verify`, `disable`, and `remove` calls to one registered configuration and the Authentication plugin API. It never returns a hash, and creation returns the plaintext once. The service supports database storage only; callers own authorization, the resources they bind keys to, and restrictions on public self-service endpoints. No application-specific scope or App identity is built into this plugin.
|
|
161
|
+
|
|
162
|
+
Server calls run through `Auth.pluginApi()` and the normal Better Auth hooks; `withConnection(connection)` binds all credential writes to a caller-owned transaction. The added get/delete operations are declared with `createAuthEndpoint.serverOnly` and cannot be reached over HTTP.
|
|
163
|
+
|
|
164
|
+
`findRequestApiKey(plugin, headers)` returns the key a request carries, read from the headers of every configuration that resolves keys into sessions, and `createApiKeyApiDocsAccess(resolveAuth)` is the API document access check the plugin's server registers; an application assembling its own providers can register it on `apiDocsToken` itself. `Auth.plugin<ApiKeysPlugin>('api-key')?.options.configurations` holds the configurations `apiKey()` was created with, after its defaults.
|
|
165
|
+
|
|
166
|
+
Trusted lifecycle integrations can call `removeUserApiKeys(connection, userId, configIds)` within their user-deletion transaction to remove database-backed credentials for explicit user-referencing configurations. Do not pass organization-referencing or custom-storage configurations. Hub uses `default` and `hub-publishing`; dependent Hub bindings are removed by foreign-key cascades.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { ApiKey } from '@better-auth/api-key';
|
|
2
|
+
import type { apiKeyClient } from '@better-auth/api-key/client';
|
|
3
|
+
/**
|
|
4
|
+
* Better Auth's API Key client plugin, which an application adds to `plugins`
|
|
5
|
+
* in `client/config/auth.ts` so `authClient.apiKey.*` reaches the endpoints
|
|
6
|
+
* the server plugin mounts.
|
|
7
|
+
*/
|
|
8
|
+
export { apiKeyClient } from '@better-auth/api-key/client';
|
|
9
|
+
declare module '@nocobase/app-plugin-authentication/client' {
|
|
10
|
+
interface AuthClientPluginRegistry {
|
|
11
|
+
'api-key': ReturnType<typeof apiKeyClient>;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A key as the list endpoint returns it: Better Auth's own model, minus the
|
|
16
|
+
* hash the endpoint strips before responding.
|
|
17
|
+
*/
|
|
18
|
+
export type ApiKeySummary = Omit<ApiKey, 'key'>;
|
|
19
|
+
//# sourceMappingURL=api-keys-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-keys-client.d.ts","sourceRoot":"","sources":["../../client/api-keys-client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AACnD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAEhE;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAG3D,OAAO,QAAQ,4CAA4C,CAAC;IAC1D,UAAU,wBAAwB;QAChC,SAAS,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;KAC5C;CACF;AAED;;;GAGG;AACH,MAAM,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Better Auth's API Key client plugin, which an application adds to `plugins`
|
|
3
|
+
* in `client/config/auth.ts` so `authClient.apiKey.*` reaches the endpoints
|
|
4
|
+
* the server plugin mounts.
|
|
5
|
+
*/
|
|
6
|
+
export { apiKeyClient } from '@better-auth/api-key/client';
|
|
7
|
+
//# sourceMappingURL=api-keys-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"api-keys-client.js","sourceRoot":"","sources":["../../client/api-keys-client.ts"],"names":[],"mappings":"AAGA;;;;GAIG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-container.d.ts","sourceRoot":"","sources":["../../../client/components/page-container.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1D,MAAM,MAAM,kBAAkB,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;AAE3D,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,kBAAkB,GAAG,YAAY,CAOnC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from 'cn';
|
|
3
|
+
export function PageContainer({ className, ...props }) {
|
|
4
|
+
return (_jsx("section", { className: cn('w-full space-y-6 p-6 md:p-8', className), ...props }));
|
|
5
|
+
}
|
|
6
|
+
//# sourceMappingURL=page-container.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-container.js","sourceRoot":"","sources":["../../../client/components/page-container.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAIxB,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,GAAG,KAAK,EACW;IACnB,OAAO,CACL,kBACE,SAAS,EAAE,EAAE,CAAC,6BAA6B,EAAE,SAAS,CAAC,KACnD,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { ReactNode, ReactElement } from 'react';
|
|
2
|
+
export interface PageHeaderProps {
|
|
3
|
+
readonly title: ReactNode;
|
|
4
|
+
readonly description?: ReactNode;
|
|
5
|
+
readonly actions?: ReactNode;
|
|
6
|
+
}
|
|
7
|
+
export declare function PageHeader({ actions, description, title, }: PageHeaderProps): ReactElement;
|
|
8
|
+
//# sourceMappingURL=page-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-header.d.ts","sourceRoot":"","sources":["../../../client/components/page-header.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAErD,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC;IAC1B,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,CAAC;IACjC,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;CAC9B;AAED,wBAAgB,UAAU,CAAC,EACzB,OAAO,EACP,WAAW,EACX,KAAK,GACN,EAAE,eAAe,GAAG,YAAY,CAkBhC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
export function PageHeader({ actions, description, title, }) {
|
|
3
|
+
return (_jsxs("header", { className: 'flex flex-col gap-4 sm:flex-row sm:items-end sm:justify-between', children: [_jsxs("div", { className: 'min-w-0', children: [_jsx("h1", { className: 'font-heading text-3xl font-semibold tracking-[-0.035em]', children: title }), description ? (_jsx("p", { className: 'mt-2 max-w-2xl text-sm leading-6 text-muted-foreground', children: description })) : null] }), actions ? (_jsx("div", { className: 'flex shrink-0 items-center gap-2', children: actions })) : null] }));
|
|
4
|
+
}
|
|
5
|
+
//# sourceMappingURL=page-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-header.js","sourceRoot":"","sources":["../../../client/components/page-header.tsx"],"names":[],"mappings":";AAQA,MAAM,UAAU,UAAU,CAAC,EACzB,OAAO,EACP,WAAW,EACX,KAAK,GACW;IAChB,OAAO,CACL,kBAAQ,SAAS,EAAC,iEAAiE,aACjF,eAAK,SAAS,EAAC,SAAS,aACtB,aAAI,SAAS,EAAC,yDAAyD,YACpE,KAAK,GACH,EACJ,WAAW,CAAC,CAAC,CAAC,CACb,YAAG,SAAS,EAAC,wDAAwD,YAClE,WAAW,GACV,CACL,CAAC,CAAC,CAAC,IAAI,IACJ,EACL,OAAO,CAAC,CAAC,CAAC,CACT,cAAK,SAAS,EAAC,kCAAkC,YAAE,OAAO,GAAO,CAClE,CAAC,CAAC,CAAC,IAAI,IACD,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { AlertDialog as AlertDialogPrimitive } from '@base-ui/react/alert-dialog';
|
|
3
|
+
import { Button } from './button.js';
|
|
4
|
+
declare function AlertDialog({ ...props }: AlertDialogPrimitive.Root.Props): React.JSX.Element;
|
|
5
|
+
declare function AlertDialogTrigger({ ...props }: AlertDialogPrimitive.Trigger.Props): React.JSX.Element;
|
|
6
|
+
declare function AlertDialogPortal({ ...props }: AlertDialogPrimitive.Portal.Props): React.JSX.Element;
|
|
7
|
+
declare function AlertDialogOverlay({ className, ...props }: AlertDialogPrimitive.Backdrop.Props): React.JSX.Element;
|
|
8
|
+
declare function AlertDialogContent({ className, size, ...props }: AlertDialogPrimitive.Popup.Props & {
|
|
9
|
+
size?: 'default' | 'sm';
|
|
10
|
+
}): React.JSX.Element;
|
|
11
|
+
declare function AlertDialogHeader({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
12
|
+
declare function AlertDialogFooter({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
13
|
+
declare function AlertDialogMedia({ className, ...props }: React.ComponentProps<'div'>): React.JSX.Element;
|
|
14
|
+
declare function AlertDialogTitle({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Title>): React.JSX.Element;
|
|
15
|
+
declare function AlertDialogDescription({ className, ...props }: React.ComponentProps<typeof AlertDialogPrimitive.Description>): React.JSX.Element;
|
|
16
|
+
declare function AlertDialogAction({ className, ...props }: React.ComponentProps<typeof Button>): React.JSX.Element;
|
|
17
|
+
declare function AlertDialogCancel({ className, variant, size, ...props }: AlertDialogPrimitive.Close.Props & Pick<React.ComponentProps<typeof Button>, 'variant' | 'size'>): React.JSX.Element;
|
|
18
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, };
|
|
19
|
+
//# sourceMappingURL=alert-dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alert-dialog.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/alert-dialog.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAGlF,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,iBAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAErD;AAED,iBAAS,kBAAkB,CAAC,EAC1B,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAIxD;AAED,iBAAS,iBAAiB,CAAC,EACzB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,MAAM,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAIvD;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,QAAQ,CAAC,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAWzD;AAED,iBAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,GAAG;IACpC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,CAAC;CACzB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAepB;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAWjD;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAWjD;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAWjD;AAED,iBAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,oBAAoB,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAW7E;AAED,iBAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CACrB,OAAO,oBAAoB,CAAC,WAAW,CACxC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAWpB;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAQzD;AAED,iBAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,OAAmB,EACnB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,oBAAoB,CAAC,KAAK,CAAC,KAAK,GACjC,IAAI,CACF,KAAK,CAAC,cAAc,CAAC,OAAO,MAAM,CAAC,EACnC,SAAS,GAAG,MAAM,CACnB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAStB;AAED,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,CAAC"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { AlertDialog as AlertDialogPrimitive } from '@base-ui/react/alert-dialog';
|
|
3
|
+
import { cn } from 'cn';
|
|
4
|
+
import { Button } from './button.js';
|
|
5
|
+
function AlertDialog({ ...props }) {
|
|
6
|
+
return _jsx(AlertDialogPrimitive.Root, { "data-slot": 'alert-dialog', ...props });
|
|
7
|
+
}
|
|
8
|
+
function AlertDialogTrigger({ ...props }) {
|
|
9
|
+
return (_jsx(AlertDialogPrimitive.Trigger, { "data-slot": 'alert-dialog-trigger', ...props }));
|
|
10
|
+
}
|
|
11
|
+
function AlertDialogPortal({ ...props }) {
|
|
12
|
+
return (_jsx(AlertDialogPrimitive.Portal, { "data-slot": 'alert-dialog-portal', ...props }));
|
|
13
|
+
}
|
|
14
|
+
function AlertDialogOverlay({ className, ...props }) {
|
|
15
|
+
return (_jsx(AlertDialogPrimitive.Backdrop, { "data-slot": 'alert-dialog-overlay', className: cn('fixed inset-0 isolate z-50 bg-black/10 duration-100 supports-backdrop-filter:backdrop-blur-xs data-open:animate-in data-open:fade-in-0 data-closed:animate-out data-closed:fade-out-0', className), ...props }));
|
|
16
|
+
}
|
|
17
|
+
function AlertDialogContent({ className, size = 'default', ...props }) {
|
|
18
|
+
return (_jsxs(AlertDialogPortal, { children: [_jsx(AlertDialogOverlay, {}), _jsx(AlertDialogPrimitive.Popup, { "data-slot": 'alert-dialog-content', "data-size": size, className: cn('group/alert-dialog-content fixed top-1/2 left-1/2 z-50 grid w-full -translate-x-1/2 -translate-y-1/2 gap-4 rounded-xl bg-popover p-4 text-popover-foreground ring-1 ring-foreground/10 duration-100 outline-none data-[size=default]:max-w-xs data-[size=sm]:max-w-xs data-[size=default]:sm:max-w-sm data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95', className), ...props })] }));
|
|
19
|
+
}
|
|
20
|
+
function AlertDialogHeader({ className, ...props }) {
|
|
21
|
+
return (_jsx("div", { "data-slot": 'alert-dialog-header', className: cn('grid grid-rows-[auto_1fr] place-items-center gap-1.5 text-center has-data-[slot=alert-dialog-media]:grid-rows-[auto_auto_1fr] has-data-[slot=alert-dialog-media]:gap-x-4 sm:group-data-[size=default]/alert-dialog-content:place-items-start sm:group-data-[size=default]/alert-dialog-content:text-left sm:group-data-[size=default]/alert-dialog-content:has-data-[slot=alert-dialog-media]:grid-rows-[auto_1fr]', className), ...props }));
|
|
22
|
+
}
|
|
23
|
+
function AlertDialogFooter({ className, ...props }) {
|
|
24
|
+
return (_jsx("div", { "data-slot": 'alert-dialog-footer', className: cn('-mx-4 -mb-4 flex flex-col-reverse gap-2 rounded-b-xl border-t bg-muted/50 p-4 group-data-[size=sm]/alert-dialog-content:grid group-data-[size=sm]/alert-dialog-content:grid-cols-2 sm:flex-row sm:justify-end', className), ...props }));
|
|
25
|
+
}
|
|
26
|
+
function AlertDialogMedia({ className, ...props }) {
|
|
27
|
+
return (_jsx("div", { "data-slot": 'alert-dialog-media', className: cn("mb-2 inline-flex size-10 items-center justify-center rounded-md bg-muted sm:group-data-[size=default]/alert-dialog-content:row-span-2 *:[svg:not([class*='size-'])]:size-6", className), ...props }));
|
|
28
|
+
}
|
|
29
|
+
function AlertDialogTitle({ className, ...props }) {
|
|
30
|
+
return (_jsx(AlertDialogPrimitive.Title, { "data-slot": 'alert-dialog-title', className: cn('font-heading text-base font-medium sm:group-data-[size=default]/alert-dialog-content:group-has-data-[slot=alert-dialog-media]/alert-dialog-content:col-start-2', className), ...props }));
|
|
31
|
+
}
|
|
32
|
+
function AlertDialogDescription({ className, ...props }) {
|
|
33
|
+
return (_jsx(AlertDialogPrimitive.Description, { "data-slot": 'alert-dialog-description', className: cn('text-sm text-balance text-muted-foreground md:text-pretty *:[a]:underline *:[a]:underline-offset-3 *:[a]:hover:text-foreground', className), ...props }));
|
|
34
|
+
}
|
|
35
|
+
function AlertDialogAction({ className, ...props }) {
|
|
36
|
+
return (_jsx(Button, { "data-slot": 'alert-dialog-action', className: cn(className), ...props }));
|
|
37
|
+
}
|
|
38
|
+
function AlertDialogCancel({ className, variant = 'outline', size = 'default', ...props }) {
|
|
39
|
+
return (_jsx(AlertDialogPrimitive.Close, { "data-slot": 'alert-dialog-cancel', className: cn(className), render: _jsx(Button, { variant: variant, size: size }), ...props }));
|
|
40
|
+
}
|
|
41
|
+
export { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogMedia, AlertDialogOverlay, AlertDialogPortal, AlertDialogTitle, AlertDialogTrigger, };
|
|
42
|
+
//# sourceMappingURL=alert-dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"alert-dialog.js","sourceRoot":"","sources":["../../../../client/components/ui/alert-dialog.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,WAAW,IAAI,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAClF,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAExB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,SAAS,WAAW,CAAC,EACnB,GAAG,KAAK,EACwB;IAChC,OAAO,KAAC,oBAAoB,CAAC,IAAI,iBAAW,cAAc,KAAK,KAAK,GAAI,CAAC;AAC3E,CAAC;AAED,SAAS,kBAAkB,CAAC,EAC1B,GAAG,KAAK,EAC2B;IACnC,OAAO,CACL,KAAC,oBAAoB,CAAC,OAAO,iBAAW,sBAAsB,KAAK,KAAK,GAAI,CAC7E,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,EACzB,GAAG,KAAK,EAC0B;IAClC,OAAO,CACL,KAAC,oBAAoB,CAAC,MAAM,iBAAW,qBAAqB,KAAK,KAAK,GAAI,CAC3E,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,GAAG,KAAK,EAC4B;IACpC,OAAO,CACL,KAAC,oBAAoB,CAAC,QAAQ,iBAClB,sBAAsB,EAChC,SAAS,EAAE,EAAE,CACX,uLAAuL,EACvL,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,kBAAkB,CAAC,EAC1B,SAAS,EACT,IAAI,GAAG,SAAS,EAChB,GAAG,KAAK,EAGT;IACC,OAAO,CACL,MAAC,iBAAiB,eAChB,KAAC,kBAAkB,KAAG,EACtB,KAAC,oBAAoB,CAAC,KAAK,iBACf,sBAAsB,eACrB,IAAI,EACf,SAAS,EAAE,EAAE,CACX,4aAA4a,EAC5a,SAAS,CACV,KACG,KAAK,GACT,IACgB,CACrB,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACoB;IAC5B,OAAO,CACL,2BACY,qBAAqB,EAC/B,SAAS,EAAE,EAAE,CACX,oZAAoZ,EACpZ,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EACoB;IAC5B,OAAO,CACL,2BACY,qBAAqB,EAC/B,SAAS,EAAE,EAAE,CACX,+MAA+M,EAC/M,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACoB;IAC5B,OAAO,CACL,2BACY,oBAAoB,EAC9B,SAAS,EAAE,EAAE,CACX,4KAA4K,EAC5K,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,gBAAgB,CAAC,EACxB,SAAS,EACT,GAAG,KAAK,EACgD;IACxD,OAAO,CACL,KAAC,oBAAoB,CAAC,KAAK,iBACf,oBAAoB,EAC9B,SAAS,EAAE,EAAE,CACX,gKAAgK,EAChK,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,sBAAsB,CAAC,EAC9B,SAAS,EACT,GAAG,KAAK,EAGT;IACC,OAAO,CACL,KAAC,oBAAoB,CAAC,WAAW,iBACrB,0BAA0B,EACpC,SAAS,EAAE,EAAE,CACX,gIAAgI,EAChI,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,GAAG,KAAK,EAC4B;IACpC,OAAO,CACL,KAAC,MAAM,iBACK,qBAAqB,EAC/B,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,KACpB,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,SAAS,iBAAiB,CAAC,EACzB,SAAS,EACT,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,SAAS,EAChB,GAAG,KAAK,EAKP;IACD,OAAO,CACL,KAAC,oBAAoB,CAAC,KAAK,iBACf,qBAAqB,EAC/B,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,EACxB,MAAM,EAAE,KAAC,MAAM,IAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,GAAI,KAC5C,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,OAAO,EACL,WAAW,EACX,iBAAiB,EACjB,iBAAiB,EACjB,kBAAkB,EAClB,sBAAsB,EACtB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,gBAAgB,EAChB,kBAAkB,GACnB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { ComponentProps, ReactElement } from 'react';
|
|
2
|
+
export type BadgeProps = ComponentProps<'span'> & {
|
|
3
|
+
readonly variant?: 'default' | 'secondary';
|
|
4
|
+
};
|
|
5
|
+
export declare function Badge({ className, variant, ...props }: BadgeProps): ReactElement;
|
|
6
|
+
//# sourceMappingURL=badge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/badge.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1D,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,GAAG;IAChD,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,WAAW,CAAC;CAC5C,CAAC;AAEF,wBAAgB,KAAK,CAAC,EACpB,SAAS,EACT,OAAmB,EACnB,GAAG,KAAK,EACT,EAAE,UAAU,GAAG,YAAY,CAa3B"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { cn } from 'cn';
|
|
3
|
+
export function Badge({ className, variant = 'default', ...props }) {
|
|
4
|
+
return (_jsx("span", { className: cn('inline-flex w-fit items-center rounded-full px-2 py-0.5 text-xs font-medium', variant === 'default'
|
|
5
|
+
? 'bg-primary text-primary-foreground'
|
|
6
|
+
: 'bg-secondary text-secondary-foreground', className), ...props }));
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=badge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"badge.js","sourceRoot":"","sources":["../../../../client/components/ui/badge.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAMxB,MAAM,UAAU,KAAK,CAAC,EACpB,SAAS,EACT,OAAO,GAAG,SAAS,EACnB,GAAG,KAAK,EACG;IACX,OAAO,CACL,eACE,SAAS,EAAE,EAAE,CACX,6EAA6E,EAC7E,OAAO,KAAK,SAAS;YACnB,CAAC,CAAC,oCAAoC;YACtC,CAAC,CAAC,wCAAwC,EAC5C,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Button as ButtonPrimitive } from '@base-ui/react/button';
|
|
2
|
+
import type { ReactElement } from 'react';
|
|
3
|
+
export type ButtonProps = ButtonPrimitive.Props & {
|
|
4
|
+
readonly size?: 'default' | 'sm' | 'lg' | 'icon' | 'icon-sm';
|
|
5
|
+
readonly variant?: 'default' | 'outline' | 'ghost' | 'destructive';
|
|
6
|
+
};
|
|
7
|
+
export declare function Button({ className, variant, size, ...props }: ButtonProps): ReactElement;
|
|
8
|
+
//# sourceMappingURL=button.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/button.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1C,MAAM,MAAM,WAAW,GAAG,eAAe,CAAC,KAAK,GAAG;IAChD,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,GAAG,IAAI,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IAC7D,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,GAAG,aAAa,CAAC;CACpE,CAAC;AAyBF,wBAAgB,MAAM,CAAC,EACrB,SAAS,EACT,OAAmB,EACnB,IAAgB,EAChB,GAAG,KAAK,EACT,EAAE,WAAW,GAAG,YAAY,CAQ5B"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// shadcn base-nova source adapted for declaration-emitting ESM builds.
|
|
3
|
+
import { Button as ButtonPrimitive } from '@base-ui/react/button';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
5
|
+
import { cn } from 'cn';
|
|
6
|
+
const buttonVariants = cva('inline-flex shrink-0 items-center justify-center rounded-lg border border-transparent text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0', {
|
|
7
|
+
variants: {
|
|
8
|
+
variant: {
|
|
9
|
+
default: 'bg-primary text-primary-foreground hover:bg-primary/80',
|
|
10
|
+
outline: 'border-border bg-background hover:bg-muted',
|
|
11
|
+
ghost: 'hover:bg-muted',
|
|
12
|
+
destructive: 'bg-destructive/10 text-destructive hover:bg-destructive/20',
|
|
13
|
+
},
|
|
14
|
+
size: {
|
|
15
|
+
default: 'h-9 gap-1.5 px-3',
|
|
16
|
+
sm: 'h-8 gap-1 px-2.5',
|
|
17
|
+
lg: 'h-10 gap-2 px-4',
|
|
18
|
+
icon: 'size-9',
|
|
19
|
+
'icon-sm': 'size-8',
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
defaultVariants: { variant: 'default', size: 'default' },
|
|
23
|
+
});
|
|
24
|
+
export function Button({ className, variant = 'default', size = 'default', ...props }) {
|
|
25
|
+
return (_jsx(ButtonPrimitive, { "data-slot": 'button', className: cn(buttonVariants({ variant, size }), className), ...props }));
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=button.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"button.js","sourceRoot":"","sources":["../../../../client/components/ui/button.tsx"],"names":[],"mappings":";AAAA,uEAAuE;AACvE,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAG/C,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAOxB,MAAM,cAAc,GAAG,GAAG,CACxB,gVAAgV,EAChV;IACE,QAAQ,EAAE;QACR,OAAO,EAAE;YACP,OAAO,EAAE,wDAAwD;YACjE,OAAO,EAAE,4CAA4C;YACrD,KAAK,EAAE,gBAAgB;YACvB,WAAW,EACT,4DAA4D;SAC/D;QACD,IAAI,EAAE;YACJ,OAAO,EAAE,kBAAkB;YAC3B,EAAE,EAAE,kBAAkB;YACtB,EAAE,EAAE,iBAAiB;YACrB,IAAI,EAAE,QAAQ;YACd,SAAS,EAAE,QAAQ;SACpB;KACF;IACD,eAAe,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,IAAI,EAAE,SAAS,EAAE;CACzD,CACF,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,EACrB,SAAS,EACT,OAAO,GAAG,SAAS,EACnB,IAAI,GAAG,SAAS,EAChB,GAAG,KAAK,EACI;IACZ,OAAO,CACL,KAAC,eAAe,iBACJ,QAAQ,EAClB,SAAS,EAAE,EAAE,CAAC,cAAc,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,SAAS,CAAC,KACvD,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
2
|
+
import type { ComponentProps, ReactElement } from 'react';
|
|
3
|
+
export declare function Dialog(props: DialogPrimitive.Root.Props): ReactElement;
|
|
4
|
+
export declare function DialogContent(inputProps: DialogPrimitive.Popup.Props): ReactElement;
|
|
5
|
+
export declare function DialogHeader({ className, ...props }: ComponentProps<'div'>): ReactElement;
|
|
6
|
+
export declare function DialogFooter({ className, ...props }: ComponentProps<'div'>): ReactElement;
|
|
7
|
+
export declare function DialogTitle(props: DialogPrimitive.Title.Props): ReactElement;
|
|
8
|
+
export declare function DialogDescription(props: DialogPrimitive.Description.Props): ReactElement;
|
|
9
|
+
//# sourceMappingURL=dialog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/dialog.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1D,wBAAgB,MAAM,CAAC,KAAK,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,GAAG,YAAY,CAEtE;AACD,wBAAgB,aAAa,CAC3B,UAAU,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,GACtC,YAAY,CA8Bd;AACD,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAEtC;AACD,wBAAgB,YAAY,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAWtC;AACD,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,GAAG,YAAY,CAE5E;AACD,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,eAAe,CAAC,WAAW,CAAC,KAAK,GACvC,YAAY,CAOd"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from '@nocobase/i18n/client';
|
|
3
|
+
// shadcn base-nova source adapted for declaration-emitting ESM builds.
|
|
4
|
+
import { Dialog as DialogPrimitive } from '@base-ui/react/dialog';
|
|
5
|
+
import { X } from 'lucide-react';
|
|
6
|
+
import { cn } from 'cn';
|
|
7
|
+
import { Button } from './button.js';
|
|
8
|
+
export function Dialog(props) {
|
|
9
|
+
return _jsx(DialogPrimitive.Root, { ...props });
|
|
10
|
+
}
|
|
11
|
+
export function DialogContent(inputProps) {
|
|
12
|
+
const { t } = useTranslation('@nocobase/app-plugin-api-keys');
|
|
13
|
+
const { className, children, ...props } = inputProps;
|
|
14
|
+
return (_jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Backdrop, { className: 'fixed inset-0 z-50 bg-black/45' }), _jsxs(DialogPrimitive.Popup, { className: cn('fixed top-1/2 left-1/2 z-50 max-h-[calc(100dvh-2rem)] w-full max-w-[calc(100%-2rem)] sm:max-w-md -translate-x-1/2 -translate-y-1/2 overflow-y-auto rounded-2xl border bg-background p-6 shadow-2xl outline-none', className), ...props, children: [children, _jsx(DialogPrimitive.Close, { render: _jsx(Button, { "aria-label": t('common.close', { defaultValue: 'Close' }), className: 'absolute top-4 right-4', size: 'icon-sm', variant: 'ghost' }), children: _jsx(X, {}) })] })] }));
|
|
15
|
+
}
|
|
16
|
+
export function DialogHeader({ className, ...props }) {
|
|
17
|
+
return _jsx("div", { className: cn('space-y-1', className), ...props });
|
|
18
|
+
}
|
|
19
|
+
export function DialogFooter({ className, ...props }) {
|
|
20
|
+
// Sticks to the bottom of the scrolling panel, so a long body never scrolls the buttons away.
|
|
21
|
+
return (_jsx("div", { className: cn('sticky -bottom-6 z-10 -mx-6 -mb-6 mt-6 flex justify-end gap-2 rounded-b-2xl border-t bg-background px-6 py-4', className), ...props }));
|
|
22
|
+
}
|
|
23
|
+
export function DialogTitle(props) {
|
|
24
|
+
return _jsx(DialogPrimitive.Title, { className: 'text-xl font-semibold', ...props });
|
|
25
|
+
}
|
|
26
|
+
export function DialogDescription(props) {
|
|
27
|
+
return (_jsx(DialogPrimitive.Description, { className: 'text-sm text-muted-foreground', ...props }));
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=dialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dialog.js","sourceRoot":"","sources":["../../../../client/components/ui/dialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,uEAAuE;AACvE,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,CAAC,EAAE,MAAM,cAAc,CAAC;AAGjC,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AACxB,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,UAAU,MAAM,CAAC,KAAiC;IACtD,OAAO,KAAC,eAAe,CAAC,IAAI,OAAK,KAAK,GAAI,CAAC;AAC7C,CAAC;AACD,MAAM,UAAU,aAAa,CAC3B,UAAuC;IAEvC,MAAM,EAAE,CAAC,EAAE,GAAG,cAAc,CAAC,+BAA+B,CAAC,CAAC;IAC9D,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,GAAG,KAAK,EAAE,GAAG,UAAU,CAAC;IAErD,OAAO,CACL,MAAC,eAAe,CAAC,MAAM,eACrB,KAAC,eAAe,CAAC,QAAQ,IAAC,SAAS,EAAC,gCAAgC,GAAG,EACvE,MAAC,eAAe,CAAC,KAAK,IACpB,SAAS,EAAE,EAAE,CACX,iNAAiN,EACjN,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,KAAC,eAAe,CAAC,KAAK,IACpB,MAAM,EACJ,KAAC,MAAM,kBACO,CAAC,CAAC,cAAc,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,CAAC,EACxD,SAAS,EAAC,wBAAwB,EAClC,IAAI,EAAC,SAAS,EACd,OAAO,EAAC,OAAO,GACf,YAGJ,KAAC,CAAC,KAAG,GACiB,IACF,IACD,CAC1B,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACc;IACtB,OAAO,cAAK,SAAS,EAAE,EAAE,CAAC,WAAW,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAAC;AACnE,CAAC;AACD,MAAM,UAAU,YAAY,CAAC,EAC3B,SAAS,EACT,GAAG,KAAK,EACc;IACtB,8FAA8F;IAC9F,OAAO,CACL,cACE,SAAS,EAAE,EAAE,CACX,8GAA8G,EAC9G,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,WAAW,CAAC,KAAkC;IAC5D,OAAO,KAAC,eAAe,CAAC,KAAK,IAAC,SAAS,EAAC,uBAAuB,KAAK,KAAK,GAAI,CAAC;AAChF,CAAC;AACD,MAAM,UAAU,iBAAiB,CAC/B,KAAwC;IAExC,OAAO,CACL,KAAC,eAAe,CAAC,WAAW,IAC1B,SAAS,EAAC,+BAA+B,KACrC,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/input.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1D,MAAM,MAAM,UAAU,GAAG,cAAc,CAAC,OAAO,CAAC,CAAC;AAEjD,wBAAgB,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAE,EAAE,UAAU,GAAG,YAAY,CAY7E"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
// shadcn base-nova source adapted for declaration-emitting ESM builds.
|
|
3
|
+
import { Input as InputPrimitive } from '@base-ui/react/input';
|
|
4
|
+
import { cn } from 'cn';
|
|
5
|
+
export function Input({ className, type, ...props }) {
|
|
6
|
+
return (_jsx(InputPrimitive, { "data-slot": 'input', type: type, className: cn('h-9 w-full min-w-0 rounded-lg border border-input bg-transparent px-3 py-1 text-sm outline-none placeholder:text-muted-foreground focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50', className), ...props }));
|
|
7
|
+
}
|
|
8
|
+
//# sourceMappingURL=input.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"input.js","sourceRoot":"","sources":["../../../../client/components/ui/input.tsx"],"names":[],"mappings":";AAAA,uEAAuE;AACvE,OAAO,EAAE,KAAK,IAAI,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAG/D,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAIxB,MAAM,UAAU,KAAK,CAAC,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,EAAc;IAC7D,OAAO,CACL,KAAC,cAAc,iBACH,OAAO,EACjB,IAAI,EAAE,IAAI,EACV,SAAS,EAAE,EAAE,CACX,8PAA8P,EAC9P,SAAS,CACV,KACG,KAAK,GACT,CACH,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/label.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1D,wBAAgB,KAAK,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACT,EAAE,cAAc,CAAC,OAAO,CAAC,GAAG,YAAY,CAExC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"label.js","sourceRoot":"","sources":["../../../../client/components/ui/label.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAExB,MAAM,UAAU,KAAK,CAAC,EACpB,SAAS,EACT,GAAG,KAAK,EACgB;IACxB,OAAO,gBAAO,SAAS,EAAE,EAAE,CAAC,qBAAqB,EAAE,SAAS,CAAC,KAAM,KAAK,GAAI,CAAC;AAC/E,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { Select as SelectPrimitive } from '@base-ui/react/select';
|
|
2
|
+
import type { ReactElement } from 'react';
|
|
3
|
+
export declare const Select: typeof SelectPrimitive.Root;
|
|
4
|
+
export declare function SelectValue(props: SelectPrimitive.Value.Props): ReactElement;
|
|
5
|
+
export declare function SelectTrigger({ className, children, ...props }: SelectPrimitive.Trigger.Props): ReactElement;
|
|
6
|
+
export declare function SelectContent({ className, children, sideOffset, ...props }: SelectPrimitive.Popup.Props & Pick<SelectPrimitive.Positioner.Props, 'sideOffset'>): ReactElement;
|
|
7
|
+
export declare function SelectItem({ className, children, ...props }: SelectPrimitive.Item.Props): ReactElement;
|
|
8
|
+
//# sourceMappingURL=select.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/select.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAElE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1C,eAAO,MAAM,MAAM,EAAE,OAAO,eAAe,CAAC,IAA2B,CAAC;AAExE,wBAAgB,WAAW,CAAC,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,GAAG,YAAY,CAE5E;AACD,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,OAAO,CAAC,KAAK,GAAG,YAAY,CAe9C;AACD,wBAAgB,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,UAAc,EACd,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,GAC5B,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,KAAK,EAAE,YAAY,CAAC,GAAG,YAAY,CAmBpE;AACD,wBAAgB,UAAU,CAAC,EACzB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACT,EAAE,eAAe,CAAC,IAAI,CAAC,KAAK,GAAG,YAAY,CAe3C"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
// shadcn base-nova source adapted for declaration-emitting ESM builds.
|
|
3
|
+
import { Select as SelectPrimitive } from '@base-ui/react/select';
|
|
4
|
+
import { Check, ChevronDown } from 'lucide-react';
|
|
5
|
+
import { cn } from 'cn';
|
|
6
|
+
export const Select = SelectPrimitive.Root;
|
|
7
|
+
export function SelectValue(props) {
|
|
8
|
+
return _jsx(SelectPrimitive.Value, { className: 'flex flex-1 text-left', ...props });
|
|
9
|
+
}
|
|
10
|
+
export function SelectTrigger({ className, children, ...props }) {
|
|
11
|
+
return (_jsxs(SelectPrimitive.Trigger, { className: cn('flex h-9 items-center justify-between gap-2 rounded-lg border bg-background px-3 text-sm outline-none focus-visible:ring-3 focus-visible:ring-ring/50 disabled:opacity-50', className), ...props, children: [children, _jsx(SelectPrimitive.Icon, { render: _jsx(ChevronDown, { className: 'size-4 text-muted-foreground' }) })] }));
|
|
12
|
+
}
|
|
13
|
+
export function SelectContent({ className, children, sideOffset = 4, ...props }) {
|
|
14
|
+
return (_jsx(SelectPrimitive.Portal, { children: _jsx(SelectPrimitive.Positioner, { sideOffset: sideOffset, className: 'isolate z-50', children: _jsx(SelectPrimitive.Popup, { className: cn('max-h-(--available-height) min-w-36 overflow-y-auto rounded-lg bg-popover p-1 shadow-md ring-1 ring-foreground/10', className), ...props, children: _jsx(SelectPrimitive.List, { children: children }) }) }) }));
|
|
15
|
+
}
|
|
16
|
+
export function SelectItem({ className, children, ...props }) {
|
|
17
|
+
return (_jsxs(SelectPrimitive.Item, { className: cn('relative flex cursor-default items-center rounded-md py-1.5 pr-8 pl-2 text-sm outline-none focus:bg-accent data-disabled:opacity-50', className), ...props, children: [_jsx(SelectPrimitive.ItemText, { children: children }), _jsx(SelectPrimitive.ItemIndicator, { className: 'absolute right-2', children: _jsx(Check, { className: 'size-4' }) })] }));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../../client/components/ui/select.tsx"],"names":[],"mappings":";AAAA,uEAAuE;AACvE,OAAO,EAAE,MAAM,IAAI,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAGlD,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AAExB,MAAM,CAAC,MAAM,MAAM,GAAgC,eAAe,CAAC,IAAI,CAAC;AAExE,MAAM,UAAU,WAAW,CAAC,KAAkC;IAC5D,OAAO,KAAC,eAAe,CAAC,KAAK,IAAC,SAAS,EAAC,uBAAuB,KAAK,KAAK,GAAI,CAAC;AAChF,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACsB;IAC9B,OAAO,CACL,MAAC,eAAe,CAAC,OAAO,IACtB,SAAS,EAAE,EAAE,CACX,2KAA2K,EAC3K,SAAS,CACV,KACG,KAAK,aAER,QAAQ,EACT,KAAC,eAAe,CAAC,IAAI,IACnB,MAAM,EAAE,KAAC,WAAW,IAAC,SAAS,EAAC,8BAA8B,GAAG,GAChE,IACsB,CAC3B,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,aAAa,CAAC,EAC5B,SAAS,EACT,QAAQ,EACR,UAAU,GAAG,CAAC,EACd,GAAG,KAAK,EAE4C;IACpD,OAAO,CACL,KAAC,eAAe,CAAC,MAAM,cACrB,KAAC,eAAe,CAAC,UAAU,IACzB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAC,cAAc,YAExB,KAAC,eAAe,CAAC,KAAK,IACpB,SAAS,EAAE,EAAE,CACX,mHAAmH,EACnH,SAAS,CACV,KACG,KAAK,YAET,KAAC,eAAe,CAAC,IAAI,cAAE,QAAQ,GAAwB,GACjC,GACG,GACN,CAC1B,CAAC;AACJ,CAAC;AACD,MAAM,UAAU,UAAU,CAAC,EACzB,SAAS,EACT,QAAQ,EACR,GAAG,KAAK,EACmB;IAC3B,OAAO,CACL,MAAC,eAAe,CAAC,IAAI,IACnB,SAAS,EAAE,EAAE,CACX,qIAAqI,EACrI,SAAS,CACV,KACG,KAAK,aAET,KAAC,eAAe,CAAC,QAAQ,cAAE,QAAQ,GAA4B,EAC/D,KAAC,eAAe,CAAC,aAAa,IAAC,SAAS,EAAC,kBAAkB,YACzD,KAAC,KAAK,IAAC,SAAS,EAAC,QAAQ,GAAG,GACE,IACX,CACxB,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../../../client/components/ui/spinner.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAK1C,iBAAS,OAAO,CAAC,UAAU,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,GAAG,YAAY,CAatE;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { useTranslation } from '@nocobase/i18n/client';
|
|
3
|
+
import { cn } from 'cn';
|
|
4
|
+
import { Loader2Icon } from 'lucide-react';
|
|
5
|
+
function Spinner(inputProps) {
|
|
6
|
+
const { t } = useTranslation();
|
|
7
|
+
const { className, ...props } = inputProps;
|
|
8
|
+
return (_jsx(Loader2Icon, { "data-slot": 'spinner', role: 'status', "aria-label": t('status.loading', { defaultValue: 'Loading' }), className: cn('size-4 animate-spin', className), ...props }));
|
|
9
|
+
}
|
|
10
|
+
export { Spinner };
|
|
11
|
+
//# sourceMappingURL=spinner.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../../../client/components/ui/spinner.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,EAAE,EAAE,MAAM,IAAI,CAAC;AACxB,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,SAAS,OAAO,CAAC,UAAuC;IACtD,MAAM,EAAE,CAAC,EAAE,GAAG,cAAc,EAAE,CAAC;IAC/B,MAAM,EAAE,SAAS,EAAE,GAAG,KAAK,EAAE,GAAG,UAAU,CAAC;IAE3C,OAAO,CACL,KAAC,WAAW,iBACA,SAAS,EACnB,IAAI,EAAC,QAAQ,gBACD,CAAC,CAAC,gBAAgB,EAAE,EAAE,YAAY,EAAE,SAAS,EAAE,CAAC,EAC5D,SAAS,EAAE,EAAE,CAAC,qBAAqB,EAAE,SAAS,CAAC,KAC3C,KAAK,GACT,CACH,CAAC;AACJ,CAAC;AAED,OAAO,EAAE,OAAO,EAAE,CAAC"}
|