@colixsystems/widget-sdk 0.13.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +78 -3
- package/dist/clipboard.js +88 -0
- package/dist/clipboard.native.js +64 -0
- package/dist/contract.cjs +318 -11
- package/dist/contract.js +280 -9
- package/dist/datetimepicker.js +102 -0
- package/dist/hooks.js +233 -1
- package/dist/icon.js +29 -0
- package/dist/index.d.ts +126 -0
- package/dist/index.js +10 -0
- package/dist/index.native.js +8 -0
- package/dist/linter.cjs +243 -9
- package/dist/linter.js +309 -10
- package/dist/primitives.js +8 -0
- package/dist/primitives.native.js +9 -0
- package/dist/property-schema.js +7 -0
- package/dist/toast.js +73 -0
- package/dist/toast.native.js +46 -0
- package/package.json +2 -2
package/dist/hooks.js
CHANGED
|
@@ -61,7 +61,9 @@ export function WidgetContextProvider({ value, children }) {
|
|
|
61
61
|
return React.createElement(HostWidgetContext.Provider, { value }, children);
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
-
|
|
64
|
+
// Exported for ./toast.js + future hook modules outside hooks.js. Internal
|
|
65
|
+
// utility — widget code should not import this directly.
|
|
66
|
+
export function useWidgetContextOrThrow(hookName) {
|
|
65
67
|
const ctx = useContext(HostWidgetContext);
|
|
66
68
|
if (ctx == null) {
|
|
67
69
|
throw new Error(
|
|
@@ -687,6 +689,236 @@ export function usePayments() {
|
|
|
687
689
|
* the key is missing. The host's i18n.t may or may not honour the two-arg
|
|
688
690
|
* form; we degrade gracefully either way.
|
|
689
691
|
*/
|
|
692
|
+
/**
|
|
693
|
+
* REQ-USERMGMT / REQ-ACL-SYS M3 — structured error thrown by `useUsers` /
|
|
694
|
+
* `useGroups` callbacks. Carries a stable `code` so widgets can branch
|
|
695
|
+
* without parsing message strings.
|
|
696
|
+
*
|
|
697
|
+
* `code` is one of:
|
|
698
|
+
* - "FORBIDDEN" — 403 from the host (capability or scope missing).
|
|
699
|
+
* - "VALIDATION" — 400 / 422 (bad email, duplicate, etc.).
|
|
700
|
+
* - "NOT_FOUND" — 404 (group / user does not exist or cross-tenant).
|
|
701
|
+
* - "INVITE_ONLY" — 409 from accept-invite-style flows where the tenant
|
|
702
|
+
* is invite-only and the email is not on the list.
|
|
703
|
+
* - "INTERNAL" — anything else (network, 5xx).
|
|
704
|
+
*/
|
|
705
|
+
export class DirectoryError extends Error {
|
|
706
|
+
constructor(code, message, opts) {
|
|
707
|
+
super(message);
|
|
708
|
+
this.name = "DirectoryError";
|
|
709
|
+
this.code = code;
|
|
710
|
+
if (opts && opts.cause) this.cause = opts.cause;
|
|
711
|
+
}
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
function toDirectoryError(err) {
|
|
715
|
+
if (err instanceof DirectoryError) return err;
|
|
716
|
+
const status =
|
|
717
|
+
err && err.response && typeof err.response.status === "number"
|
|
718
|
+
? err.response.status
|
|
719
|
+
: null;
|
|
720
|
+
const bodyCode =
|
|
721
|
+
err && err.response && err.response.data && err.response.data.code;
|
|
722
|
+
const bodyMessage =
|
|
723
|
+
err && err.response && err.response.data && err.response.data.error;
|
|
724
|
+
let code = "INTERNAL";
|
|
725
|
+
if (bodyCode === "INVITE_ONLY") code = "INVITE_ONLY";
|
|
726
|
+
else if (status === 403) code = "FORBIDDEN";
|
|
727
|
+
else if (status === 404) code = "NOT_FOUND";
|
|
728
|
+
else if (status === 400 || status === 422) code = "VALIDATION";
|
|
729
|
+
else if (status === 409) {
|
|
730
|
+
// 409 is invite-only on the invite endpoints; treat the rest as
|
|
731
|
+
// validation conflicts (duplicate email, etc.).
|
|
732
|
+
code = bodyCode === "INVITE_ONLY" ? "INVITE_ONLY" : "VALIDATION";
|
|
733
|
+
}
|
|
734
|
+
const message =
|
|
735
|
+
(typeof bodyMessage === "string" && bodyMessage) ||
|
|
736
|
+
(err && typeof err.message === "string"
|
|
737
|
+
? err.message
|
|
738
|
+
: "Directory call failed");
|
|
739
|
+
return new DirectoryError(code, message, { cause: err });
|
|
740
|
+
}
|
|
741
|
+
|
|
742
|
+
/**
|
|
743
|
+
* REQ-USERMGMT / REQ-ACL-SYS M3 — AppUser administration hook.
|
|
744
|
+
*
|
|
745
|
+
* Returns `{ users, loading, error, refetch, invite, deactivate,
|
|
746
|
+
* reactivate, remove }`. The list refetches whenever
|
|
747
|
+
* `JSON.stringify(query)` changes; the imperative methods reject with a
|
|
748
|
+
* `DirectoryError`. Reads require the `users.read:*` scope; mutations
|
|
749
|
+
* additionally require `users.write:*`. The host's signed
|
|
750
|
+
* `X-Widget-Scopes` header + a tenant-scoped SystemAcl `users.read` /
|
|
751
|
+
* `users.write` capability grant gate the underlying endpoint
|
|
752
|
+
* (REQ-ACL-SYS M3 §4.3) — a widget that declares the scopes but whose
|
|
753
|
+
* caller does not hold the grant gets a `FORBIDDEN`.
|
|
754
|
+
*/
|
|
755
|
+
export function useUsers(query) {
|
|
756
|
+
const ctx = useWidgetContextOrThrow("useUsers");
|
|
757
|
+
if (!ctx.users || typeof ctx.users.listUsers !== "function") {
|
|
758
|
+
throw new Error("useUsers: host did not inject a users client");
|
|
759
|
+
}
|
|
760
|
+
const [users, setUsers] = useState([]);
|
|
761
|
+
const [loading, setLoading] = useState(true);
|
|
762
|
+
const [error, setError] = useState(null);
|
|
763
|
+
|
|
764
|
+
const queryRef = useRef(query);
|
|
765
|
+
const usersRef = useRef(ctx.users);
|
|
766
|
+
queryRef.current = query;
|
|
767
|
+
usersRef.current = ctx.users;
|
|
768
|
+
|
|
769
|
+
const runRef = useRef(0);
|
|
770
|
+
|
|
771
|
+
const doFetch = useCallback(async () => {
|
|
772
|
+
const myRun = ++runRef.current;
|
|
773
|
+
setLoading(true);
|
|
774
|
+
setError(null);
|
|
775
|
+
try {
|
|
776
|
+
const rows = await usersRef.current.listUsers(queryRef.current);
|
|
777
|
+
if (runRef.current !== myRun) return;
|
|
778
|
+
setUsers(Array.isArray(rows) ? rows : []);
|
|
779
|
+
setLoading(false);
|
|
780
|
+
} catch (err) {
|
|
781
|
+
if (runRef.current !== myRun) return;
|
|
782
|
+
setError(toDirectoryError(err));
|
|
783
|
+
setLoading(false);
|
|
784
|
+
}
|
|
785
|
+
}, []);
|
|
786
|
+
|
|
787
|
+
const queryKey = (() => {
|
|
788
|
+
try {
|
|
789
|
+
return JSON.stringify(query);
|
|
790
|
+
} catch (_e) {
|
|
791
|
+
return null;
|
|
792
|
+
}
|
|
793
|
+
})();
|
|
794
|
+
useEffect(() => {
|
|
795
|
+
doFetch();
|
|
796
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
797
|
+
}, [queryKey]);
|
|
798
|
+
|
|
799
|
+
const refetch = useCallback(async () => {
|
|
800
|
+
await doFetch();
|
|
801
|
+
}, [doFetch]);
|
|
802
|
+
|
|
803
|
+
const invite = useCallback(async (args) => {
|
|
804
|
+
try {
|
|
805
|
+
return await usersRef.current.invite(args);
|
|
806
|
+
} catch (err) {
|
|
807
|
+
throw toDirectoryError(err);
|
|
808
|
+
}
|
|
809
|
+
}, []);
|
|
810
|
+
const deactivate = useCallback(async (userId) => {
|
|
811
|
+
try {
|
|
812
|
+
return await usersRef.current.deactivate(userId);
|
|
813
|
+
} catch (err) {
|
|
814
|
+
throw toDirectoryError(err);
|
|
815
|
+
}
|
|
816
|
+
}, []);
|
|
817
|
+
const reactivate = useCallback(async (userId) => {
|
|
818
|
+
try {
|
|
819
|
+
return await usersRef.current.reactivate(userId);
|
|
820
|
+
} catch (err) {
|
|
821
|
+
throw toDirectoryError(err);
|
|
822
|
+
}
|
|
823
|
+
}, []);
|
|
824
|
+
const remove = useCallback(async (userId) => {
|
|
825
|
+
try {
|
|
826
|
+
return await usersRef.current.remove(userId);
|
|
827
|
+
} catch (err) {
|
|
828
|
+
throw toDirectoryError(err);
|
|
829
|
+
}
|
|
830
|
+
}, []);
|
|
831
|
+
|
|
832
|
+
return { users, loading, error, refetch, invite, deactivate, reactivate, remove };
|
|
833
|
+
}
|
|
834
|
+
|
|
835
|
+
/**
|
|
836
|
+
* REQ-USERMGMT / REQ-ACL-SYS M3 — AppUserGroup administration hook.
|
|
837
|
+
*
|
|
838
|
+
* Returns `{ groups, loading, error, refetch, create, remove, addMember,
|
|
839
|
+
* removeMember }`. Reads require `groups.read:*`; mutations require
|
|
840
|
+
* `groups.write:*`. Same X-Widget-Scopes + SystemAcl gating as `useUsers`.
|
|
841
|
+
*/
|
|
842
|
+
export function useGroups(query) {
|
|
843
|
+
const ctx = useWidgetContextOrThrow("useGroups");
|
|
844
|
+
if (!ctx.groups || typeof ctx.groups.listGroups !== "function") {
|
|
845
|
+
throw new Error("useGroups: host did not inject a groups client");
|
|
846
|
+
}
|
|
847
|
+
const [groups, setGroups] = useState([]);
|
|
848
|
+
const [loading, setLoading] = useState(true);
|
|
849
|
+
const [error, setError] = useState(null);
|
|
850
|
+
|
|
851
|
+
const queryRef = useRef(query);
|
|
852
|
+
const groupsRef = useRef(ctx.groups);
|
|
853
|
+
queryRef.current = query;
|
|
854
|
+
groupsRef.current = ctx.groups;
|
|
855
|
+
|
|
856
|
+
const runRef = useRef(0);
|
|
857
|
+
|
|
858
|
+
const doFetch = useCallback(async () => {
|
|
859
|
+
const myRun = ++runRef.current;
|
|
860
|
+
setLoading(true);
|
|
861
|
+
setError(null);
|
|
862
|
+
try {
|
|
863
|
+
const rows = await groupsRef.current.listGroups(queryRef.current);
|
|
864
|
+
if (runRef.current !== myRun) return;
|
|
865
|
+
setGroups(Array.isArray(rows) ? rows : []);
|
|
866
|
+
setLoading(false);
|
|
867
|
+
} catch (err) {
|
|
868
|
+
if (runRef.current !== myRun) return;
|
|
869
|
+
setError(toDirectoryError(err));
|
|
870
|
+
setLoading(false);
|
|
871
|
+
}
|
|
872
|
+
}, []);
|
|
873
|
+
|
|
874
|
+
const queryKey = (() => {
|
|
875
|
+
try {
|
|
876
|
+
return JSON.stringify(query);
|
|
877
|
+
} catch (_e) {
|
|
878
|
+
return null;
|
|
879
|
+
}
|
|
880
|
+
})();
|
|
881
|
+
useEffect(() => {
|
|
882
|
+
doFetch();
|
|
883
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
884
|
+
}, [queryKey]);
|
|
885
|
+
|
|
886
|
+
const refetch = useCallback(async () => {
|
|
887
|
+
await doFetch();
|
|
888
|
+
}, [doFetch]);
|
|
889
|
+
|
|
890
|
+
const create = useCallback(async (args) => {
|
|
891
|
+
try {
|
|
892
|
+
return await groupsRef.current.create(args);
|
|
893
|
+
} catch (err) {
|
|
894
|
+
throw toDirectoryError(err);
|
|
895
|
+
}
|
|
896
|
+
}, []);
|
|
897
|
+
const remove = useCallback(async (groupId) => {
|
|
898
|
+
try {
|
|
899
|
+
return await groupsRef.current.remove(groupId);
|
|
900
|
+
} catch (err) {
|
|
901
|
+
throw toDirectoryError(err);
|
|
902
|
+
}
|
|
903
|
+
}, []);
|
|
904
|
+
const addMember = useCallback(async (groupId, userId) => {
|
|
905
|
+
try {
|
|
906
|
+
return await groupsRef.current.addMember(groupId, userId);
|
|
907
|
+
} catch (err) {
|
|
908
|
+
throw toDirectoryError(err);
|
|
909
|
+
}
|
|
910
|
+
}, []);
|
|
911
|
+
const removeMember = useCallback(async (groupId, userId) => {
|
|
912
|
+
try {
|
|
913
|
+
return await groupsRef.current.removeMember(groupId, userId);
|
|
914
|
+
} catch (err) {
|
|
915
|
+
throw toDirectoryError(err);
|
|
916
|
+
}
|
|
917
|
+
}, []);
|
|
918
|
+
|
|
919
|
+
return { groups, loading, error, refetch, create, remove, addMember, removeMember };
|
|
920
|
+
}
|
|
921
|
+
|
|
690
922
|
export function useI18n() {
|
|
691
923
|
const ctx = useWidgetContextOrThrow("useI18n");
|
|
692
924
|
const i18n = ctx.i18n || {};
|
package/dist/icon.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// REQ-WSDK-PLATFORM §6 — `<Icon>` SDK primitive.
|
|
2
|
+
//
|
|
3
|
+
// Wraps lucide-react-native's name-keyed component map behind a small
|
|
4
|
+
// stable API: `<Icon name="check" size={16} color="..." />`. Same source
|
|
5
|
+
// runs on both platforms — lucide-react-native ships a working web build
|
|
6
|
+
// (via the host's Vite shim) and a native build (Metro picks it
|
|
7
|
+
// straight). Unknown names fall back to the `Square` glyph so the
|
|
8
|
+
// canvas always shows something visible.
|
|
9
|
+
//
|
|
10
|
+
// The built-in `Icon` widget at frontend/src/components/widgets/Icon/
|
|
11
|
+
// already implements this exact pattern. Marketplace widgets reach for
|
|
12
|
+
// the SDK primitive instead of importing lucide-react-native directly,
|
|
13
|
+
// keeping the import-surface of a typical widget small (and avoiding the
|
|
14
|
+
// `import * as LucideIcons` pattern which trips eslint's
|
|
15
|
+
// no-restricted-syntax in some configs).
|
|
16
|
+
|
|
17
|
+
import React from "react";
|
|
18
|
+
import * as LucideIcons from "lucide-react-native";
|
|
19
|
+
|
|
20
|
+
export function Icon({ name, size, color }) {
|
|
21
|
+
const candidate =
|
|
22
|
+
typeof name === "string" && name.length > 0 ? LucideIcons[name] : null;
|
|
23
|
+
const Component = candidate || LucideIcons.Square;
|
|
24
|
+
const pixelSize = Number.isFinite(size) && size > 0 ? size : 24;
|
|
25
|
+
return React.createElement(Component, {
|
|
26
|
+
size: pixelSize,
|
|
27
|
+
color: color || "#0f172a",
|
|
28
|
+
});
|
|
29
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -28,6 +28,9 @@ export type WidgetPropertyType =
|
|
|
28
28
|
| "tableRef"
|
|
29
29
|
| "columnRef"
|
|
30
30
|
| "recordBinding"
|
|
31
|
+
// REQ-USERMGMT M4 / §4.8: Group picker that emits a bare
|
|
32
|
+
// AppUserGroup UUID into the page JSON.
|
|
33
|
+
| "groupRef"
|
|
31
34
|
| "expression"
|
|
32
35
|
| "eventBinding"
|
|
33
36
|
| "object"
|
|
@@ -480,6 +483,109 @@ export class DatastoreError extends Error {
|
|
|
480
483
|
);
|
|
481
484
|
}
|
|
482
485
|
|
|
486
|
+
/**
|
|
487
|
+
* REQ-USERMGMT / REQ-ACL-SYS M3 — error class thrown by `useUsers` and
|
|
488
|
+
* `useGroups` callbacks. The `code` is a stable categorisation widgets
|
|
489
|
+
* can branch on.
|
|
490
|
+
*/
|
|
491
|
+
export class DirectoryError extends Error {
|
|
492
|
+
code:
|
|
493
|
+
| "FORBIDDEN"
|
|
494
|
+
| "VALIDATION"
|
|
495
|
+
| "NOT_FOUND"
|
|
496
|
+
| "INVITE_ONLY"
|
|
497
|
+
| "INTERNAL";
|
|
498
|
+
constructor(
|
|
499
|
+
code: DirectoryError["code"],
|
|
500
|
+
message: string,
|
|
501
|
+
opts?: { cause?: unknown },
|
|
502
|
+
);
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
// --------------------------------------------------------------- useUsers
|
|
506
|
+
//
|
|
507
|
+
// REQ-USERMGMT / REQ-ACL-SYS M3 — AppUser administration hook.
|
|
508
|
+
|
|
509
|
+
export interface AppUserRow {
|
|
510
|
+
id: string;
|
|
511
|
+
name: string;
|
|
512
|
+
email?: string;
|
|
513
|
+
role: "USER" | "INTEGRATION";
|
|
514
|
+
isActive: boolean;
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
export interface UsersQuery {
|
|
518
|
+
q?: string;
|
|
519
|
+
role?: "USER" | "INTEGRATION" | "ALL";
|
|
520
|
+
isActive?: boolean;
|
|
521
|
+
limit?: number;
|
|
522
|
+
offset?: number;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
export interface InviteArgs {
|
|
526
|
+
email: string;
|
|
527
|
+
name?: string;
|
|
528
|
+
groupIds?: string[];
|
|
529
|
+
}
|
|
530
|
+
|
|
531
|
+
export interface AppUserInviteRow {
|
|
532
|
+
id: string;
|
|
533
|
+
email: string;
|
|
534
|
+
status: string;
|
|
535
|
+
invitedAt?: string;
|
|
536
|
+
expiresAt?: string;
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
export interface UsersApi {
|
|
540
|
+
users: AppUserRow[];
|
|
541
|
+
loading: boolean;
|
|
542
|
+
error: DirectoryError | null;
|
|
543
|
+
refetch(): Promise<void>;
|
|
544
|
+
invite(args: InviteArgs): Promise<AppUserInviteRow>;
|
|
545
|
+
deactivate(userId: string): Promise<AppUserRow>;
|
|
546
|
+
reactivate(userId: string): Promise<AppUserRow>;
|
|
547
|
+
remove(userId: string): Promise<void>;
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
/**
|
|
551
|
+
* AppUser administration. Reads require the `users.read:*` scope in the
|
|
552
|
+
* manifest; mutations additionally require `users.write:*`. Widgets that
|
|
553
|
+
* declare the scopes but whose calling APP_USER lacks the corresponding
|
|
554
|
+
* SystemAcl `users.*` capability grant get a `FORBIDDEN` DirectoryError.
|
|
555
|
+
*/
|
|
556
|
+
export function useUsers(query?: UsersQuery): UsersApi;
|
|
557
|
+
|
|
558
|
+
// --------------------------------------------------------------- useGroups
|
|
559
|
+
|
|
560
|
+
export interface AppUserGroupRow {
|
|
561
|
+
id: string;
|
|
562
|
+
name: string;
|
|
563
|
+
memberCount?: number;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
export interface GroupsQuery {
|
|
567
|
+
q?: string;
|
|
568
|
+
limit?: number;
|
|
569
|
+
offset?: number;
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
export interface GroupsApi {
|
|
573
|
+
groups: AppUserGroupRow[];
|
|
574
|
+
loading: boolean;
|
|
575
|
+
error: DirectoryError | null;
|
|
576
|
+
refetch(): Promise<void>;
|
|
577
|
+
create(args: { name: string }): Promise<AppUserGroupRow>;
|
|
578
|
+
remove(groupId: string): Promise<void>;
|
|
579
|
+
addMember(groupId: string, userId: string): Promise<void>;
|
|
580
|
+
removeMember(groupId: string, userId: string): Promise<void>;
|
|
581
|
+
}
|
|
582
|
+
|
|
583
|
+
/**
|
|
584
|
+
* AppUserGroup administration. Reads require `groups.read:*`; mutations
|
|
585
|
+
* require `groups.write:*`. Same SystemAcl gating as `useUsers`.
|
|
586
|
+
*/
|
|
587
|
+
export function useGroups(query?: GroupsQuery): GroupsApi;
|
|
588
|
+
|
|
483
589
|
export function WidgetContextProvider(props: {
|
|
484
590
|
value: WidgetContext;
|
|
485
591
|
children?: ReactNode;
|
|
@@ -501,9 +607,29 @@ export const ActivityIndicator: any;
|
|
|
501
607
|
export const Switch: any;
|
|
502
608
|
export const StyleSheet: any;
|
|
503
609
|
|
|
610
|
+
/**
|
|
611
|
+
* REQ-WSDK-PLATFORM §6 — Lucide icon primitive. Unknown names fall back
|
|
612
|
+
* to the `Square` glyph so the canvas always shows something visible.
|
|
613
|
+
*
|
|
614
|
+
* @example
|
|
615
|
+
* import { Icon } from '@colixsystems/widget-sdk';
|
|
616
|
+
* <Icon name="check" size={16} color={theme.colors.primary} />
|
|
617
|
+
*/
|
|
618
|
+
export const Icon: (props: {
|
|
619
|
+
name?: string;
|
|
620
|
+
size?: number;
|
|
621
|
+
color?: string;
|
|
622
|
+
}) => any;
|
|
623
|
+
|
|
504
624
|
// Linter
|
|
505
625
|
export interface LintFinding {
|
|
506
626
|
rule: string;
|
|
627
|
+
/**
|
|
628
|
+
* REQ-WSDK-PLATFORM update: findings can now carry a `severity`. The
|
|
629
|
+
* lint's `ok` flag is true iff no `severity: "error"` finding exists.
|
|
630
|
+
* `severity: "warning"` findings surface to reviewers but do not block.
|
|
631
|
+
*/
|
|
632
|
+
severity?: "error" | "warning";
|
|
507
633
|
label: string;
|
|
508
634
|
line: number;
|
|
509
635
|
snippet: string;
|
package/dist/index.js
CHANGED
|
@@ -9,11 +9,14 @@ export {
|
|
|
9
9
|
WidgetContextProvider,
|
|
10
10
|
DatastoreError,
|
|
11
11
|
PaymentError,
|
|
12
|
+
DirectoryError,
|
|
12
13
|
useDatastoreQuery,
|
|
13
14
|
useDatastoreRecord,
|
|
14
15
|
useFile,
|
|
15
16
|
useDatastoreMutation,
|
|
16
17
|
useDirectory,
|
|
18
|
+
useUsers,
|
|
19
|
+
useGroups,
|
|
17
20
|
useWidgetEvent,
|
|
18
21
|
usePayments,
|
|
19
22
|
useTheme,
|
|
@@ -23,6 +26,11 @@ export {
|
|
|
23
26
|
useChildRenderer,
|
|
24
27
|
WidgetTree,
|
|
25
28
|
} from "./hooks.js";
|
|
29
|
+
// REQ-WSDK-PLATFORM §6 — Tier A hooks. Each ships in a per-platform file
|
|
30
|
+
// (./clipboard.js / .native.js, ./toast.js / .native.js); index.js picks
|
|
31
|
+
// the web variant and index.native.js picks the native variant.
|
|
32
|
+
export { useClipboard, ClipboardError } from "./clipboard.js";
|
|
33
|
+
export { useToast } from "./toast.js";
|
|
26
34
|
export {
|
|
27
35
|
Text,
|
|
28
36
|
View,
|
|
@@ -36,6 +44,8 @@ export {
|
|
|
36
44
|
Switch,
|
|
37
45
|
StyleSheet,
|
|
38
46
|
Linking,
|
|
47
|
+
Icon,
|
|
48
|
+
DateTimePicker,
|
|
39
49
|
} from "./primitives.js";
|
|
40
50
|
export { lintSource, bannedIdentifiers } from "./linter.js";
|
|
41
51
|
export { CONTRACT, isHookAllowed, requiredContextKeys } from "./contract.js";
|
package/dist/index.native.js
CHANGED
|
@@ -9,11 +9,14 @@ export {
|
|
|
9
9
|
WidgetContextProvider,
|
|
10
10
|
DatastoreError,
|
|
11
11
|
PaymentError,
|
|
12
|
+
DirectoryError,
|
|
12
13
|
useDatastoreQuery,
|
|
13
14
|
useDatastoreRecord,
|
|
14
15
|
useFile,
|
|
15
16
|
useDatastoreMutation,
|
|
16
17
|
useDirectory,
|
|
18
|
+
useUsers,
|
|
19
|
+
useGroups,
|
|
17
20
|
useWidgetEvent,
|
|
18
21
|
usePayments,
|
|
19
22
|
useTheme,
|
|
@@ -23,6 +26,9 @@ export {
|
|
|
23
26
|
useChildRenderer,
|
|
24
27
|
WidgetTree,
|
|
25
28
|
} from "./hooks.js";
|
|
29
|
+
// REQ-WSDK-PLATFORM §6 — Tier A hooks (native variants).
|
|
30
|
+
export { useClipboard, ClipboardError } from "./clipboard.native.js";
|
|
31
|
+
export { useToast } from "./toast.native.js";
|
|
26
32
|
export {
|
|
27
33
|
Text,
|
|
28
34
|
View,
|
|
@@ -36,6 +42,8 @@ export {
|
|
|
36
42
|
Switch,
|
|
37
43
|
StyleSheet,
|
|
38
44
|
Linking,
|
|
45
|
+
Icon,
|
|
46
|
+
DateTimePicker,
|
|
39
47
|
} from "./primitives.native.js";
|
|
40
48
|
export { lintSource, bannedIdentifiers } from "./linter.js";
|
|
41
49
|
export { CONTRACT, isHookAllowed, requiredContextKeys } from "./contract.js";
|