@datawheel/bespoke 1.0.0-rc.2 → 1.0.0-rc.21

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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # Reports
2
2
 
3
+ ## Documentation
4
+
5
+ - **[Customization Guide](./docs/customization.md)** - Overview of styling and component customization options
6
+ - **[Styling Guide](./docs/customization/styles.md)** - Detailed CSS/SCSS customization reference
7
+ - **[Custom Components Guide](./docs/customization/components.md)** - How to override default components
8
+
3
9
  ## EnvVars
4
10
 
5
11
  ```
@@ -16,9 +22,10 @@ NEXT_PUBLIC_IMAGE_SPLASH_WIDTH=1400
16
22
  NEXT_PUBLIC_IMAGE_THUMB_WIDTH=400
17
23
 
18
24
  # Providers
19
- NEXT_PUBLIC_IMAGE_PROVIDERS="upload,local,flickr,unsplash,adobe"
25
+ NEXT_PUBLIC_IMAGE_PROVIDERS="upload,local,flickr,unsplash,adobe,pixabay"
20
26
  FLICKR_API_KEY="xxxx"
21
27
  UNSPLASH_API_KEY="xxxx"
28
+ PIXABAY_API_KEY="xxxx"
22
29
  # unused ADOBE_STOCK_API_KEY="xxxx"
23
30
  # unused ADOBE_STOCK_API_SECRET="xxxx"
24
31
  # unused ADOBE_MANAGEMENT_API_KEY="xxxx"
@@ -56,3 +63,5 @@ publicRuntimeConfig: {
56
63
  ```
57
64
 
58
65
  And is gonna be offered as ENV_API and ENV_WHATEVER in the list of variables in the profile.
66
+
67
+ ## SCSS Mixins
@@ -0,0 +1,178 @@
1
+ @use "sass:string";
2
+ @use "sass:math";
3
+
4
+ /* -----------------------------------
5
+ Bespoke Component Mixins
6
+ ----------------------------------- */
7
+
8
+ /// @mixin bespoke($component, $element)
9
+ /// Converts @bespoke(Component, element) into :global(.bespoke-Component-element)
10
+ @mixin bespoke($component, $element: "root") {
11
+ // 1. Construct the class name: .bespoke-Component-element
12
+ $class-name: ".bespoke-" + $component + "-" + $element;
13
+
14
+ // 2. Construct the full selector: :global(.bespoke-Component-element)
15
+ $selector: ":global(" + $class-name + ")";
16
+
17
+ // 3. Output the selector and its content placeholder
18
+ // The @content directive allows you to pass CSS rules to the mixin call
19
+
20
+ #{$selector} {
21
+ @content;
22
+ }
23
+ }
24
+
25
+
26
+ /* -----------------------------------
27
+ Mantine Mixins
28
+ ----------------------------------- */
29
+
30
+ // Define variables for your breakpoints,
31
+ // values must be the same as in your theme
32
+ $mantine-breakpoint-xs: '36em';
33
+ $mantine-breakpoint-sm: '48em';
34
+ $mantine-breakpoint-md: '62em';
35
+ $mantine-breakpoint-lg: '75em';
36
+ $mantine-breakpoint-xl: '94em';
37
+
38
+ @function rem($value) {
39
+ @return #{math.div(math.div($value, $value * 0 + 1), 16)}rem;
40
+ }
41
+
42
+ @mixin light {
43
+ [data-mantine-color-scheme='light'] & {
44
+ @content;
45
+ }
46
+ }
47
+
48
+ @mixin dark {
49
+ [data-mantine-color-scheme='dark'] & {
50
+ @content;
51
+ }
52
+ }
53
+
54
+ @mixin hover {
55
+ @media (hover: hover) {
56
+ &:hover {
57
+ @content;
58
+ }
59
+ }
60
+
61
+ @media (hover: none) {
62
+ &:active {
63
+ @content;
64
+ }
65
+ }
66
+ }
67
+
68
+ @mixin smaller-than($breakpoint) {
69
+ @media (max-width: $breakpoint) {
70
+ @content;
71
+ }
72
+ }
73
+
74
+ @mixin larger-than($breakpoint) {
75
+ @media (min-width: $breakpoint) {
76
+ @content;
77
+ }
78
+ }
79
+
80
+ // Add direction mixins if you need rtl support
81
+ @mixin rtl {
82
+ [dir='rtl'] & {
83
+ @content;
84
+ }
85
+ }
86
+
87
+ @mixin ltr {
88
+ [dir='ltr'] & {
89
+ @content;
90
+ }
91
+ }
92
+
93
+
94
+ /* -----------------------------------
95
+ Accessibility
96
+ ----------------------------------- */
97
+
98
+ /* accessibly hidden text and elements */
99
+ @mixin visually-hidden {
100
+ clip: rect(1px, 1px, 1px, 1px);
101
+ position: absolute !important;
102
+ height: 1px;
103
+ width: 1px;
104
+ overflow: hidden;
105
+ }
106
+
107
+ /* reset visually-hidden properties */
108
+ @mixin reset-visually-hidden {
109
+ clip: auto;
110
+ position: relative !important;
111
+ height: auto;
112
+ width: 100%;
113
+ overflow: auto;
114
+ }
115
+
116
+
117
+ /* -----------------------------------
118
+ Layout
119
+ ----------------------------------- */
120
+
121
+ @mixin clearfix {
122
+ &:after {
123
+ content: "";
124
+ display: table;
125
+ clear: both;
126
+ }
127
+ }
128
+
129
+ /* fill up all the space — make sure the parent has pos:rel */
130
+ @mixin absolute-expand {
131
+ position: absolute;
132
+ top: 0; right: 0; bottom: 0; left: 0;
133
+ width: 100%;
134
+ height: 100%;
135
+ }
136
+
137
+ /* center elements the dumb but sometimes useful way */
138
+ @mixin absolute-center {
139
+ position: absolute;
140
+ top: 50%;
141
+ left: 50%;
142
+ transform: translate(-50%, -50%);
143
+ }
144
+ @mixin absolute-vertical-center {
145
+ position: absolute;
146
+ top: 50%;
147
+ transform: translate(0, -50%);
148
+ }
149
+ @mixin absolute-horizontal-center {
150
+ position: absolute;
151
+ left: 50%;
152
+ transform: translate(-50%, 0);
153
+ }
154
+
155
+ @mixin hide-scrollbars {
156
+ &::-webkit-scrollbar {
157
+ display: none;
158
+ }
159
+ }
160
+
161
+ /* overflow with inertia scrolling */
162
+ @mixin overflow-container {
163
+ overflow: auto;
164
+ overscroll-behavior: contain;
165
+ -webkit-overflow-scrolling: touch;
166
+ }
167
+ @mixin vertical-overflow-container {
168
+ overflow-y: auto;
169
+ overscroll-behavior-y: contain;
170
+ -webkit-overflow-scrolling: touch;
171
+ }
172
+ @mixin horizontal-overflow-container {
173
+ overflow-x: auto;
174
+ overscroll-behavior-x: contain;
175
+ -webkit-overflow-scrolling: touch;
176
+ }
177
+
178
+
@@ -0,0 +1,129 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { ReactNode } from 'react';
3
+ import { u as SearchReportItem, i as SearchReportParams } from './types-WI9fSG9b.mjs';
4
+ import { AutocompleteProps, TooltipProps } from '@mantine/core';
5
+
6
+ interface ReportTileProps {
7
+ reportId: string;
8
+ reportName: string;
9
+ members: Array<{
10
+ original_id: string;
11
+ name: string;
12
+ id: number;
13
+ variant: string;
14
+ variant_id: number;
15
+ dimension: string;
16
+ dimension_id: number;
17
+ image: {
18
+ src: string;
19
+ alt: string;
20
+ };
21
+ }>;
22
+ href: string;
23
+ onClick: (e: React.MouseEvent) => void;
24
+ }
25
+
26
+ type TranslationKeys = "try_another" | "search" | "filters_all" | "no_results" | "load_more" | "select_report" | "select_variant" | "count_format";
27
+ type MetaTranslations = {
28
+ dimension?: Record<string, string>;
29
+ dimensionIcon?: Record<string, string>;
30
+ report?: Record<string, string>;
31
+ variant?: Record<string, string>;
32
+ variantIcon?: Record<string, string>;
33
+ tooltip?: string;
34
+ };
35
+ type ExploreTranslations = Partial<Record<TranslationKeys, string> & MetaTranslations>;
36
+ type FiltersType = {
37
+ profile?: number | undefined;
38
+ variant?: number | string | undefined;
39
+ };
40
+ interface Selector {
41
+ id?: number;
42
+ name: string;
43
+ members_count?: number;
44
+ variants?: {
45
+ id?: number;
46
+ name: string;
47
+ members_count?: number;
48
+ }[];
49
+ }
50
+ interface ExploreContextType {
51
+ metadata: any[];
52
+ loadingItems: boolean;
53
+ setLoadingItems: (q: boolean) => void;
54
+ loadingMetadata: boolean;
55
+ setLoadingMetadata: (q: boolean) => void;
56
+ resultCount: {
57
+ [key: number]: number;
58
+ };
59
+ totalCount: {
60
+ [key: number]: number;
61
+ };
62
+ setResultCount: (params: {
63
+ [key: number]: number;
64
+ } | false) => void;
65
+ activePage: number;
66
+ setActivePage: (page: number) => void;
67
+ pageSize: number;
68
+ results: SearchReportItem[];
69
+ filters: FiltersType;
70
+ doQuery: (cancelled: any, newOffset: any) => void;
71
+ setFilters: (filter: FiltersType) => void;
72
+ query: string;
73
+ setQuery: (q: string) => void;
74
+ debouncedQuery: string;
75
+ currentPageTotal: number;
76
+ selectorStructure: Selector[];
77
+ translations: ExploreTranslations;
78
+ setTranslations: (t: ExploreTranslations) => void;
79
+ showSelectors: boolean;
80
+ initExplore?: (p: number | undefined, v: number | undefined, q: string | undefined) => void;
81
+ }
82
+ declare const useExplore: () => ExploreContextType;
83
+ interface ExploreProviderProps {
84
+ children: ReactNode;
85
+ pageSize?: number;
86
+ sort?: string;
87
+ }
88
+ declare function ExploreProvider({ children, pageSize, sort }: ExploreProviderProps): react_jsx_runtime.JSX.Element;
89
+
90
+ type BespokeSearchProps = {
91
+ locale: string;
92
+ profilePrefix: string;
93
+ autocompleteProps?: Partial<AutocompleteProps & {
94
+ searchConfig: {
95
+ searchLimit?: number;
96
+ queryThreshold?: number;
97
+ };
98
+ }> | Record<string, never>;
99
+ tooltipProps?: Partial<TooltipProps>;
100
+ tooltipText?: string;
101
+ searchReportParams?: Partial<SearchReportParams>;
102
+ callback?: (item: ReportItemProps) => void;
103
+ children?: ReactNode;
104
+ };
105
+ interface ReportItemPropsInner {
106
+ id: string;
107
+ reportName: string;
108
+ reportPath: string;
109
+ profilePrefix: string;
110
+ members: Array<{
111
+ original_id: string;
112
+ name: string;
113
+ id: number;
114
+ variant: string;
115
+ image: {
116
+ src: string;
117
+ alt: string;
118
+ };
119
+ }>;
120
+ href: string;
121
+ value: string;
122
+ }
123
+ type ReportItemProps = ReportItemPropsInner;
124
+ /**
125
+ * React component for rendering an inline search autocomplete
126
+ */
127
+ declare function BespokeSearch({ locale, profilePrefix, autocompleteProps, tooltipProps, tooltipText, searchReportParams, callback, children }: BespokeSearchProps): react_jsx_runtime.JSX.Element;
128
+
129
+ export { BespokeSearch as B, type ExploreTranslations as E, type ReportTileProps as R, type ReportItemProps as a, ExploreProvider as b, useExplore as u };
@@ -0,0 +1,139 @@
1
+ import { S as SearchUsersParams, U as UpdateUserParams } from './types-WI9fSG9b.mjs';
2
+ import { User, DefaultSession, NextAuthOptions } from 'next-auth';
3
+ import { SessionContextValue } from 'next-auth/react';
4
+
5
+ interface BespokeUserInfo {
6
+ id?: string | null;
7
+ name?: string | null;
8
+ email?: string | null;
9
+ image?: string | null;
10
+ bespoke_app_metadata: {
11
+ reports?: {
12
+ reportId: number;
13
+ favorites: {
14
+ variantId: number;
15
+ contentId: number;
16
+ }[];
17
+ [key: string]: any;
18
+ }[];
19
+ [key: string]: any;
20
+ };
21
+ bespoke_user_metadata: {
22
+ preferredLocale?: string;
23
+ [key: string]: any;
24
+ };
25
+ bespoke_roles: string[];
26
+ [key: string]: any;
27
+ }
28
+ declare module "next-auth" {
29
+ interface User extends User, BespokeUserInfo {
30
+ }
31
+ interface Session extends DefaultSession {
32
+ user: BespokeUserInfo;
33
+ }
34
+ interface Profile {
35
+ bespoke_app_metadata?: {
36
+ reports?: {
37
+ reportId: number;
38
+ favorites: {
39
+ variantId: number;
40
+ contentId: number;
41
+ }[];
42
+ [key: string]: any;
43
+ }[];
44
+ preferredLocale?: string;
45
+ [key: string]: any;
46
+ };
47
+ bespoke_user_metadata?: {
48
+ preferredLocale?: string;
49
+ [key: string]: any;
50
+ };
51
+ bespoke_roles?: string[];
52
+ name?: string;
53
+ }
54
+ }
55
+ declare module "next-auth/jwt" {
56
+ interface JWT {
57
+ bespoke_app_metadata: {
58
+ reports?: {
59
+ reportId: number;
60
+ favorites: {
61
+ variantId: number;
62
+ contentId: number;
63
+ }[];
64
+ [key: string]: any;
65
+ }[];
66
+ [key: string]: any;
67
+ };
68
+ bespoke_user_metadata: {
69
+ preferredLocale?: string;
70
+ [key: string]: any;
71
+ };
72
+ bespoke_roles: string[];
73
+ }
74
+ }
75
+ /**
76
+ * Auth and roles
77
+ * There is a convention for roles names (no diference with IDs);
78
+ * "Admin" : Manage users and roles
79
+ * "Editor": Manage reports
80
+ * "Writer": Manage posts
81
+ */
82
+ declare const CMS_ROLES: {
83
+ ADMIN: string;
84
+ EDITOR: string;
85
+ WRITER: string;
86
+ };
87
+ /**
88
+ * Roles could be SYSTEM: Defined by the app and needed to work; or USER: Defined by the user
89
+ * */
90
+ declare const addRoleTypes: (roles: BespokeRole[]) => BespokeRole[];
91
+ type BespokeRole = {
92
+ id: string;
93
+ name: string;
94
+ description: string;
95
+ type?: string;
96
+ };
97
+ interface BespokeUserProfile {
98
+ app_metadata: {
99
+ reports?: {
100
+ reportId: number;
101
+ favorites: {
102
+ variantId: number;
103
+ contentId: number;
104
+ }[];
105
+ [key: string]: any;
106
+ }[];
107
+ };
108
+ user_metadata: {
109
+ preferredLocale?: string;
110
+ };
111
+ roles: BespokeRole[];
112
+ [key: string]: any;
113
+ }
114
+ type BespokeUserData = {
115
+ isLoading: boolean;
116
+ update: SessionContextValue["update"];
117
+ user?: BespokeUserInfo;
118
+ status: SessionContextValue["status"];
119
+ };
120
+ interface SearchUserResult {
121
+ users: BespokeUserProfile[];
122
+ start: number;
123
+ limit: number;
124
+ length: number;
125
+ total: number;
126
+ }
127
+ interface BespokeAuthOptions extends NextAuthOptions {
128
+ actions?: {
129
+ searchRole: () => () => Promise<{
130
+ roles: BespokeRole[];
131
+ }>;
132
+ searchUser: () => (filters: SearchUsersParams) => Promise<SearchUserResult>;
133
+ readUser: () => (userId: string) => Promise<BespokeUserProfile>;
134
+ updateUser: () => (user: UpdateUserParams) => Promise<Record<string, string>>;
135
+ };
136
+ source?: string;
137
+ }
138
+
139
+ export { type BespokeUserInfo as B, CMS_ROLES as C, type SearchUserResult as S, type BespokeUserData as a, addRoleTypes as b, type BespokeRole as c, type BespokeUserProfile as d, type BespokeAuthOptions as e };
@@ -0,0 +1,42 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import { B as BespokeUserInfo, a as BespokeUserData } from './auth-D3PWImeZ.mjs';
3
+ export { e as BespokeAuthOptions, c as BespokeRole, S as BespokeSearchUserResult, d as BespokeUserProfile, C as CMS_ROLES, b as addRoleTypes } from './auth-D3PWImeZ.mjs';
4
+ import { UseSessionOptions } from 'next-auth/react';
5
+ export { SessionProvider as BespokeUserProvider } from 'next-auth/react';
6
+ import { ButtonProps, MenuItemProps, MenuProps } from '@mantine/core';
7
+ export { S as BespokeSearchUsersParams, U as BespokeUpdateUserParams } from './types-WI9fSG9b.mjs';
8
+ import 'next-auth';
9
+ import 'sequelize';
10
+
11
+ declare function withPageRoleAuthRequired(params: {
12
+ allowedRoles: string[];
13
+ SuccessComponent: React.ComponentType<{
14
+ user: BespokeUserInfo;
15
+ }>;
16
+ FailureComponent: React.ComponentType;
17
+ }): (props: any) => react_jsx_runtime.JSX.Element;
18
+
19
+ declare function useBespokeUser(options?: UseSessionOptions<boolean>): BespokeUserData;
20
+
21
+ type BespokeLoginBtnTranslations = {
22
+ "Welcome message"?: string;
23
+ "Disconnect"?: string;
24
+ "Go to editor"?: string;
25
+ "Signing in"?: string;
26
+ "Sign in"?: string;
27
+ };
28
+ type BespokeLoginBtnProps = {
29
+ buttonProps?: ButtonProps;
30
+ editorMenuItemProps?: MenuItemProps;
31
+ editorMenuItemRoute?: string;
32
+ logoutButtonProps?: ButtonProps;
33
+ menuProps?: MenuProps;
34
+ options?: React.ReactNode;
35
+ optionsPosition?: string;
36
+ translations?: BespokeLoginBtnTranslations;
37
+ withEditorMenuItem?: boolean;
38
+ withSession?: boolean;
39
+ };
40
+ declare function BespokeLoginBtn({ buttonProps, editorMenuItemProps, editorMenuItemRoute, logoutButtonProps, menuProps, options, optionsPosition, translations, withEditorMenuItem, withSession, }: BespokeLoginBtnProps): react_jsx_runtime.JSX.Element;
41
+
42
+ export { BespokeLoginBtn, BespokeUserData, withPageRoleAuthRequired as BespokeWithPageRoleAuthRequired, useBespokeUser };
package/dist/auth.js CHANGED
@@ -1 +1 @@
1
- import {useRouter}from'next/router';import {useEffect,useMemo}from'react';import {SessionProvider,useSession,signIn,signOut}from'next-auth/react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {Menu,Button,Text,Avatar}from'@mantine/core';import {IconUserCircle,IconLogout,IconEdit}from'@tabler/icons-react';import $ from'next/link';function T(o={required:false}){let{update:i,data:s,status:a}=useSession(o);return {update:i,user:s?.user,status:a,isLoading:a==="loading"}}var g=T;function w(o){let{SuccessComponent:i,FailureComponent:s}=o,a=new Set(o.allowedRoles);return function(n){let{user:m,status:r}=g(),l=useRouter();if(useEffect(()=>{r==="unauthenticated"&&signIn();},[r,l]),r==="loading")return jsx("div",{children:"Loading..."});if(!m)return jsx(s,{...n});let y=m.bespoke_roles||[];return a.size===0||y.some(t=>a.has(t))?jsx(i,{user:m,...n}):jsx(s,{...n})}}var N=SessionProvider;var p={ADMIN:"Admin",EDITOR:"Editor",WRITER:"Writer"},I={APP:"App",USER:"User"},z=o=>{let i=Object.values(p);return o?o.map(s=>({...s,type:i.includes(s.name)?I.APP:I.USER})):[]};function J({buttonProps:o={},editorMenuItemProps:i={},editorMenuItemRoute:s="/cms",logoutButtonProps:a={},menuProps:U={},options:n="",optionsPosition:m="bottom",translations:r={},withEditorMenuItem:l=true,withSession:y=true}){let{user:t,isLoading:P}=g(),b=useMemo(()=>t?.bespoke_roles||[],[t]),k=useMemo(()=>p&&Object.keys(p).length>0&&Object.keys(p).some(S=>b.includes(p[S])),[b]),x={leftSection:jsx(IconUserCircle,{}),...o};if(t&&!P){let S={...i},M={color:"red",fullWidth:true,leftSection:jsx(IconLogout,{size:14}),size:"xs",variant:"subtle",...a},v={shadow:"md",width:"auto",position:"bottom",...U},h=jsx($,{href:s,passHref:true,children:jsx(Menu.Item,{icon:jsx(IconEdit,{size:14}),...S,children:r["Go to editor"]||"Go to editor"})});return jsxs(Menu,{...v,children:[jsx(Menu.Target,{children:jsx(Button,{...x,children:`${r["Welcome message"]||`Hi, ${t.name||t.email}`}`})}),jsxs(Menu.Dropdown,{children:[m==="top"&&jsxs(Fragment,{children:[l&&k&&h,n,(n||l&&k)&&jsx(Menu.Divider,{})]}),y&&jsxs(Menu.Item,{component:"span",style:{pointerEvents:"none"},icon:jsx(Avatar,{src:t.picture,radius:"md"}),children:[jsx(Text,{size:"sm",weight:500,children:t.name}),jsx(Text,{color:"dimmed",size:"xs",children:t.email})]}),jsx(Button,{onClick:()=>signOut({callbackUrl:process.env.NEXT_PUBLIC_REPORTS_BASE_URL||"/"}),...M,children:r.Disconnect||"Disconnect"}),m==="bottom"&&jsxs(Fragment,{children:[(n||l&&k)&&jsx(Menu.Divider,{}),l&&k&&h,n]})]})]})}return jsx(Button,{onClick:()=>signIn(),loading:P,...x,children:P?r["Signing in"]||"Signing in...":r["Sign in"]||"Sign in"})}var X=J;export{X as BespokeLoginBtn,N as BespokeUserProvider,w as BespokeWithPageRoleAuthRequired,p as CMS_ROLES,z as addRoleTypes,g as useBespokeUser};
1
+ import {useRouter}from'next/router';import {useEffect,useMemo}from'react';import {SessionProvider,useSession,signIn,signOut}from'next-auth/react';import {jsx,jsxs,Fragment}from'react/jsx-runtime';import {Menu,Button,Text,Avatar}from'@mantine/core';import {IconUserCircle,IconLogout,IconEdit}from'@tabler/icons-react';import $ from'next/link';function T(o={required:false}){let{update:i,data:s,status:a}=useSession(o);return {update:i,user:s?.user,status:a,isLoading:a==="loading"}}var f=T;function w(o){let{SuccessComponent:i,FailureComponent:s}=o,a=new Set(o.allowedRoles);return function(n){let{user:m,status:r}=f(),l=useRouter();if(useEffect(()=>{r==="unauthenticated"&&signIn();},[r,l]),r==="loading")return jsx("div",{children:"Loading..."});if(!m)return jsx(s,{...n});let y=m.bespoke_roles||[];return a.size===0||y.some(t=>a.has(t))?jsx(i,{user:m,...n}):jsx(s,{...n})}}var N=SessionProvider;var p={ADMIN:"Admin",EDITOR:"Editor",WRITER:"Writer"},I={APP:"App",USER:"User"},z=o=>{let i=Object.values(p);return o?o.map(s=>({...s,type:i.includes(s.name)?I.APP:I.USER})):[]};function J({buttonProps:o={},editorMenuItemProps:i={},editorMenuItemRoute:s="/cms",logoutButtonProps:a={},menuProps:U={},options:n="",optionsPosition:m="bottom",translations:r={},withEditorMenuItem:l=true,withSession:y=true}){let{user:t,isLoading:S}=f(),b=useMemo(()=>t?.bespoke_roles||[],[t]),k=useMemo(()=>p&&Object.keys(p).length>0&&Object.keys(p).some(P=>b.includes(p[P])),[b]),x={leftSection:jsx(IconUserCircle,{}),...o};if(t&&!S){let P={...i},M={color:"red",fullWidth:true,leftSection:jsx(IconLogout,{size:14}),size:"xs",variant:"subtle",...a},v={shadow:"md",width:"auto",position:"bottom",...U},h=jsx($,{href:s,passHref:true,children:jsx(Menu.Item,{leftSection:jsx(IconEdit,{size:14}),...P,children:r["Go to editor"]||"Go to editor"})});return jsxs(Menu,{...v,children:[jsx(Menu.Target,{children:jsx(Button,{...x,children:`${r["Welcome message"]||`Hi, ${t.name||t.email}`}`})}),jsxs(Menu.Dropdown,{children:[m==="top"&&jsxs(Fragment,{children:[l&&k&&h,n,(n||l&&k)&&jsx(Menu.Divider,{})]}),y&&jsxs(Menu.Item,{component:"span",style:{pointerEvents:"none"},leftSection:jsx(Avatar,{src:t.picture,radius:"md"}),children:[jsx(Text,{size:"sm",fw:500,children:t.name}),jsx(Text,{c:"dimmed",size:"xs",children:t.email})]}),jsx(Button,{onClick:()=>signOut({callbackUrl:process.env.NEXT_PUBLIC_REPORTS_BASE_URL||"/"}),...M,children:r.Disconnect||"Disconnect"}),m==="bottom"&&jsxs(Fragment,{children:[(n||l&&k)&&jsx(Menu.Divider,{}),l&&k&&h,n]})]})]})}return jsx(Button,{onClick:()=>signIn(),loading:S,...x,children:S?r["Signing in"]||"Signing in...":r["Sign in"]||"Sign in"})}var X=J;export{X as BespokeLoginBtn,N as BespokeUserProvider,w as BespokeWithPageRoleAuthRequired,p as CMS_ROLES,z as addRoleTypes,f as useBespokeUser};
package/dist/cms.css CHANGED
@@ -1 +1 @@
1
- .mantine-Prism-root.cr-variable{font-size:11px;padding:0}.mantine-Prism-root.cr-variable .mantine-Prism-code{background-color:transparent!important;padding:0}.cr-variable-accordion .mantine-Accordion-item{border-bottom:0}.cr-variable-accordion .mantine-Accordion-control{padding:2px}.cr-variable-accordion .mantine-Accordion-contentInner{padding:0}.cr-variable-accordion .mantine-Accordion-icon{margin-right:4px}.cr-monaco-container{height:100%}.selector-option-default-col{width:60px}.required:after{content:" *";color:red}.cr-block-output{align-items:stretch;margin:0;position:relative}.cr-block-output .cr-block-output-editor{display:flex;flex-direction:column}.cr-block-output .cr-block-output-mode-control{position:absolute;right:0;top:0}.mantine-Header-root~.mantine-AppShell-body{min-height:calc(100vh - 50px)}.cms-section-controls{height:0}.cms-section-controls button{background-color:#fff;opacity:0;transition:opacity .1s;z-index:2}.cms-section-container:hover>.cms-section-controls button{opacity:1}.cms-section-container:hover .cms-section-header,.cms-section-container:hover .cms-section-click-to-edit,.cms-section-header.active{opacity:1}.cms-section-container:hover .cms-section-overlay,.cms-section-container.isDragging .cms-section-overlay{opacity:.4}.cms-section-container .cms-section-content{min-height:20px}.mantine-Modal-body{max-height:90vw}.mantine-Prism-root pre{font-size:12px;line-height:1.25}
1
+ .C{z-index:99;overflow:hidden;transition:width .3s;box-shadow:0 4px 15px 5px #0000000d}.D{flex:1}.E{flex-grow:1}.f{display:block;width:100%}.f:hover{background-color:var(--mantine-color-gray-2)!important;transition:background-color .2s}.F{flex-shrink:0}.G{border:none;background-color:var(--mantine-color-blue-0);border-radius:var(--mantine-radius-sm);color:var(--mantine-color-blue-7);font-size:.75rem;font-weight:700;width:80px}.H{font-size:.75rem}.I{pointer-events:none}.J{max-width:100px;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.h.g{font-size:11px;padding:0}.h.g .K{background-color:transparent!important;padding:0}.i .L{border-bottom:0}.i .M{padding:2px}.i .N{padding:0}.i .O{margin-right:4px}.P{border-top-right-radius:0;border-bottom-right-radius:0}.Q{border-top-left-radius:0;border-bottom-left-radius:0;border-left:1px solid #fff;background-color:#e7f5ff;min-height:1.875rem;height:1.875rem;width:1.875rem;font-size:.75rem}.R:hover{background-color:#ebebeb}.x{box-sizing:border-box;z-index:99;transition:right .4s;overflow:hidden;background:#f1f3f5}.x[data-dragging-over=true]{background:#e7f5ff}.a{transition:background-color .45s}.a .b{opacity:0;transition:opacity .45s}.a:hover{background-color:#e9ecefe6!important}.a:hover .b{opacity:1}.m{border:none;border-radius:2px}.m[data-active=true]{border:1px solid #74c0fc}.o{background:inherit;border:1px solid transparent}.o[data-dragging-over=true]{background:#e7f5ff}.o .u{visibility:hidden}.o:hover .u{visibility:visible}.o:hover{border:1px solid #96f2d7}.n{border:1px solid transparent;resize:horizontal}.n:hover{border:1px solid transparent}.n[data-show-outline=true]:hover{border:1px solid var(--mantine-color-blue-2)}.n[data-show-outline=true]:hover:before{position:absolute;top:0;left:0;font-size:8px;color:var(--mantine-color-blue-5);transform:translateY(-100%);content:attr(data-block-label);width:-moz-fit-content;width:fit-content}.S{height:100%}.l{position:"absolute";top:"50%";z-index:10;opacity:.55}.l:hover{opacity:1}.l[data-direction=left]{left:16px}.l[data-direction=right]{right:16px}.T{table-layout:fixed}.U{min-height:100px;max-height:350px;overflow-x:"auto";background:red}.V{padding:5px!important;text-wrap:wrap}.v{display:block}@media(min-width:1000px){.v{display:none}}.y{display:none}@media(min-width:1000px){.y{display:block}}.W{border-radius:4px;transform:translate(-50%);z-index:20}.w{flex-direction:column}@media(min-width:62em){.w{flex-direction:row}}.k{max-width:100%;min-width:unset}@media(min-width:62em){.k{max-width:var(--column-max-width);min-width:300px}}.z{position:relative}.z:before{content:"";position:absolute;top:.25rem;bottom:.25rem;left:calc(.875rem + var(--level) * 1.5rem);width:.0625rem;background-color:#dee2e6;z-index:0}.d{display:flex;gap:1rem;align-items:center;list-style-type:none}.d[data-align=left]{justify-content:flex-start}.d[data-align=center]{justify-content:center}.d[data-align=right]{justify-content:flex-end}.r{display:flex}.r[data-align=left]{justify-content:flex-start}.r[data-align=center]{justify-content:center}.r[data-align=right]{justify-content:flex-end}.r li{margin-right:1rem}.j{display:flex}.j .chart{flex:1 1 100%}.X{width:60px}.Z:after{content:" *";color:red}.Y{background-color:transparent}.Y[data-selected=true]{background-color:#e7f5ff}.t{font-size:14px;line-height:1.2;background-color:var(--mantine-color-gray-0);border-color:var(--mantine-color-gray-4);border-width:1px;border-style:solid;border-radius:var(--mantine-radius-md);padding-left:var(--mantine-spacing-xs);padding-right:var(--mantine-spacing-xs);font-weight:400}.t._{color:var(--mantine-color-gray-7);background-color:var(--mantine-color-gray-1)}.t:focus-visible{outline-color:var(--mantine-color-blue-5);background-color:var(--mantine-color-gray-0)}.t code{font-family:monospace;color:var(--mantine-color-blue-6);font-weight:700;letter-spacing:.02em}.t .ee:first-of-type:before{color:var(--mantine-color-gray-6);content:attr(data-placeholder);float:left;height:0;pointer-events:none}.oe{align-items:stretch;margin:0;position:relative}.re{display:flex;flex-direction:column}.te{position:absolute;right:0;top:0}.ie{flex-grow:1;display:flex;flex-direction:column}.ae{flex-grow:1}.ne{align-self:stretch;display:flex;flex-direction:column;height:100%;position:relative}.le{align-self:stretch;display:flex;flex-direction:column;height:100%;border-left:2px solid var(--mantine-color-gray-0)}.de{display:flex;flex-direction:column;border-left:2px solid var(--mantine-color-gray-0)}.ce~.se{min-height:calc(100vh - 50px)}.p{height:0}.p button{background-color:#fff;opacity:0;transition:opacity .1s;z-index:2}.e:hover>.p button{opacity:1}.e:hover .q,.e:hover .pe,.q.fe{opacity:1}.e:hover .A,.e.he .A{opacity:.4}.e .ge{min-height:20px}.xe{max-height:90vw}.be pre{font-size:12px;line-height:1.25}.me{overflow:hidden;border-right:1px solid #dee2e6;flex-shrink:0;flex-grow:0}.B{border:1px solid transparent;cursor:default}.B:hover{border:1px solid blue}.c{cursor:default;border:1px solid transparent}.c .ue{color:var(--section-color)}.c[data-active=true]{border:1px solid #dee2e6}.c:hover{border:1px solid #339af0}.ve{overflow:hidden;border-left:1px solid #dee2e6;flex-shrink:0;flex-grow:0}.s{backdrop-filter:none;opacity:0}.s button{display:none}.s:hover{opacity:1;backdrop-filter:blur(.2375rem)}.s:hover button{display:flex}
package/dist/cms.d.mts ADDED
@@ -0,0 +1,13 @@
1
+ import { NotificationsProps } from '@mantine/notifications';
2
+
3
+ interface BespokeManagerOptions {
4
+ title?: string;
5
+ notifications?: NotificationsProps;
6
+ pathSegment?: string;
7
+ locale?: string;
8
+ profilePrefix?: string;
9
+ previewPrefix?: string | null;
10
+ }
11
+ declare function BespokeManager(options: BespokeManagerOptions): React.FC;
12
+
13
+ export { BespokeManager, type BespokeManagerOptions };