@ossy/connected-components 0.0.1-alpha → 0.0.1-beta

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.
Files changed (71) hide show
  1. package/.storybook/main.js +19 -0
  2. package/.storybook/preview.js +13 -0
  3. package/build/cjs/index.js +656 -0
  4. package/build/esm/index.js +638 -0
  5. package/package.json +49 -13
  6. package/rollup.config.js +35 -0
  7. package/src/app/App.jsx +29 -0
  8. package/src/app/App.stories.jsx +36 -0
  9. package/src/app/AppSettings.jsx +22 -0
  10. package/src/app/index.js +3 -0
  11. package/src/app/useAnalytics.jsx +18 -0
  12. package/src/index.js +11 -0
  13. package/src/layout/Layout.jsx +25 -0
  14. package/src/layout/Layout.stories.jsx +16 -0
  15. package/src/layout/index.js +1 -0
  16. package/src/ossybot/Ossybot.jsx +67 -0
  17. package/src/ossybot/Ossybot.stories.jsx +26 -0
  18. package/src/ossybot/index.js +1 -0
  19. package/src/page/Page.jsx +33 -0
  20. package/src/page/Page.stories.jsx +17 -0
  21. package/src/page/index.js +1 -0
  22. package/src/page-data-loader/PageDataLoader.jsx +90 -0
  23. package/src/page-data-loader/PageDataLoader.stories.jsx +16 -0
  24. package/src/page-data-loader/index.js +1 -0
  25. package/src/pages-module/PagesModule.jsx +8 -0
  26. package/src/pages-module/PagesModule.stories.jsx +17 -0
  27. package/src/pages-module/index.js +1 -0
  28. package/src/resume/Resume.jsx +13 -0
  29. package/src/resume/Resume.stories.jsx +23 -0
  30. package/src/resume/Resume.template.js +80 -0
  31. package/src/resume/index.js +3 -0
  32. package/src/resume/useResume.js +112 -0
  33. package/src/section/Section.jsx +93 -0
  34. package/src/section/Section.stories.jsx +17 -0
  35. package/src/section/index.js +1 -0
  36. package/src/stories/Button.jsx +39 -0
  37. package/src/stories/Button.stories.js +49 -0
  38. package/src/stories/Configure.mdx +364 -0
  39. package/src/stories/Header.jsx +56 -0
  40. package/src/stories/Header.stories.js +29 -0
  41. package/src/stories/Page.jsx +69 -0
  42. package/src/stories/Page.stories.js +28 -0
  43. package/src/stories/assets/accessibility.png +0 -0
  44. package/src/stories/assets/accessibility.svg +1 -0
  45. package/src/stories/assets/addon-library.png +0 -0
  46. package/src/stories/assets/assets.png +0 -0
  47. package/src/stories/assets/avif-test-image.avif +0 -0
  48. package/src/stories/assets/context.png +0 -0
  49. package/src/stories/assets/discord.svg +1 -0
  50. package/src/stories/assets/docs.png +0 -0
  51. package/src/stories/assets/figma-plugin.png +0 -0
  52. package/src/stories/assets/github.svg +1 -0
  53. package/src/stories/assets/share.png +0 -0
  54. package/src/stories/assets/styling.png +0 -0
  55. package/src/stories/assets/testing.png +0 -0
  56. package/src/stories/assets/theming.png +0 -0
  57. package/src/stories/assets/tutorials.svg +1 -0
  58. package/src/stories/assets/youtube.svg +1 -0
  59. package/src/stories/button.css +30 -0
  60. package/src/stories/header.css +32 -0
  61. package/src/stories/page.css +68 -0
  62. package/src/theme-editor/ThemeEditor.jsx +132 -0
  63. package/src/theme-editor/ThemeEditor.stories.jsx +16 -0
  64. package/src/theme-editor/index.js +1 -0
  65. package/src/theme-provider/ThemeProvider.jsx +9 -0
  66. package/src/theme-provider/ThemeProvider.stories.jsx +16 -0
  67. package/src/theme-provider/index.js +1 -0
  68. package/src/use-active-page-location/index.js +1 -0
  69. package/src/use-active-page-location/useActivePageLocation.js +54 -0
  70. package/index.cjs.js +0 -1
  71. package/index.esm.js +0 -1
@@ -0,0 +1,19 @@
1
+
2
+
3
+ /** @type { import('@storybook/react-vite').StorybookConfig } */
4
+ const config = {
5
+ "stories": [
6
+ "../src/**/*.mdx",
7
+ "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"
8
+ ],
9
+ "addons": [
10
+ "@storybook/addon-essentials",
11
+ "@storybook/addon-onboarding",
12
+ "@storybook/addon-interactions"
13
+ ],
14
+ "framework": {
15
+ "name": "@storybook/react-vite",
16
+ "options": {}
17
+ }
18
+ };
19
+ export default config;
@@ -0,0 +1,13 @@
1
+ /** @type { import('@storybook/react').Preview } */
2
+ const preview = {
3
+ parameters: {
4
+ controls: {
5
+ matchers: {
6
+ color: /(background|color)$/i,
7
+ date: /Date$/i,
8
+ },
9
+ },
10
+ },
11
+ };
12
+
13
+ export default preview;
@@ -0,0 +1,656 @@
1
+ 'use strict';
2
+
3
+ var React$1 = require('react');
4
+ var sdk = require('@ossy/sdk');
5
+ var sdkReact = require('@ossy/sdk-react');
6
+ var designSystem = require('@ossy/design-system');
7
+ var routerReact = require('@ossy/router-react');
8
+ var designSystemExtras = require('@ossy/design-system-extras');
9
+
10
+ const overlayStyles = {
11
+ background: 'transparent',
12
+ display: 'content',
13
+ pointerEvents: 'none'
14
+ };
15
+ const blobStyles = {
16
+ boxShadow: '2px 2px 5px hsla(0, 0%, 0%, .2)',
17
+ borderRadius: '999px',
18
+ position: 'absolute',
19
+ right: 'var(--space-m)',
20
+ bottom: 'var(--space-m)',
21
+ cursor: 'pointer',
22
+ transition: 'transform .5s',
23
+ pointerEvents: 'auto',
24
+ padding: 'var(--space-m)'
25
+ };
26
+ const editorContainerStyles = {
27
+ position: 'absolute',
28
+ right: '0',
29
+ top: '0',
30
+ height: '100%',
31
+ width: '100%',
32
+ display: 'flex',
33
+ justifyContent: 'flex-end',
34
+ alignItems: 'stretch',
35
+ padding: '8px 32px'
36
+ };
37
+ const editorStyles = {
38
+ width: '100%',
39
+ maxWidth: '350px',
40
+ height: '100%',
41
+ boxShadow: '2px 2px 5px hsla(0, 0%, 0%, .2)',
42
+ padding: '16px 16px 76px 16px',
43
+ overflowX: 'none',
44
+ overflowY: 'auto',
45
+ pointerEvents: 'auto'
46
+ };
47
+ const ThemeSwitcher = () => {
48
+ const {
49
+ activeTheme,
50
+ setTheme,
51
+ themes
52
+ } = designSystem.useTheme();
53
+ return /*#__PURE__*/React.createElement(designSystem.View, {
54
+ gap: "s"
55
+ }, /*#__PURE__*/React.createElement(designSystem.Text, null, "Theme"), /*#__PURE__*/React.createElement(designSystem.View, {
56
+ layout: "row-wrap",
57
+ gap: "s"
58
+ }, themes.map(themeName => /*#__PURE__*/React.createElement(designSystem.Button, {
59
+ variant: themeName === activeTheme ? 'tag-active' : 'tag',
60
+ onClick: () => setTheme(themeName)
61
+ }, themeName))));
62
+ };
63
+ const ThemeEditor = () => {
64
+ const {
65
+ updateResourceContent
66
+ } = sdkReact.useResource('PCX53TaGviq4_8KvK-VOp');
67
+ const [isEditorOpen, setIsEditorOpen] = React$1.useState(false);
68
+ const [viewCount, setViewCount] = React$1.useState(0);
69
+ // const [theme, temporarilyUpdateTheme] = useTheme()
70
+ const theme = {};
71
+ const toggleStyles = React$1.useMemo(() => !isEditorOpen ? blobStyles : {
72
+ ...blobStyles,
73
+ transform: 'rotate(-45deg)'
74
+ }, [isEditorOpen]);
75
+ const onToggle = React$1.useCallback(() => {
76
+ setIsEditorOpen(!isEditorOpen);
77
+ }, [isEditorOpen, setIsEditorOpen]);
78
+ const onThemeChange = event => {
79
+ const name = event.target.dataset.name;
80
+ const updatedValue = event.target.value;
81
+ if (!name) return;
82
+ if (!updatedValue) return;
83
+ };
84
+ const onSaveTheme = event => {
85
+ event.preventDefault();
86
+ updateResourceContent(theme);
87
+ };
88
+ React$1.useEffect(() => {
89
+ if (!isEditorOpen) return;
90
+ const views = document.querySelectorAll('[data-view]');
91
+ views.forEach(view => view.style.border = '1px solid red');
92
+ setViewCount(views.length);
93
+ }, [isEditorOpen]);
94
+ return /*#__PURE__*/React.createElement(designSystem.Overlay, {
95
+ isVisible: true,
96
+ style: overlayStyles
97
+ }, isEditorOpen && /*#__PURE__*/React.createElement("div", {
98
+ style: editorContainerStyles
99
+ }, /*#__PURE__*/React.createElement(designSystem.View, {
100
+ surface: "primary",
101
+ roundness: "m",
102
+ gap: "m",
103
+ style: editorStyles
104
+ }, /*#__PURE__*/React.createElement(designSystem.View, {
105
+ as: "form",
106
+ gap: "s",
107
+ onSubmit: onSaveTheme,
108
+ onChange: onThemeChange
109
+ }, Object.entries(theme).map(([name, value]) => /*#__PURE__*/React.createElement("div", {
110
+ style: {
111
+ marginBottom: '16px'
112
+ }
113
+ }, /*#__PURE__*/React.createElement("label", {
114
+ style: {
115
+ display: 'block',
116
+ fontFamily: 'sans-serif',
117
+ marginBottom: '4px',
118
+ fontWeight: 'bold'
119
+ }
120
+ }, name), /*#__PURE__*/React.createElement("input", {
121
+ value: value,
122
+ "data-name": name,
123
+ style: {
124
+ width: '100%',
125
+ padding: '4px'
126
+ }
127
+ }))), /*#__PURE__*/React.createElement(designSystem.Button, {
128
+ type: "submit",
129
+ variant: "cta"
130
+ }, "Save")), /*#__PURE__*/React.createElement(ThemeSwitcher, null), /*#__PURE__*/React.createElement(designSystem.Text, null, "Views: ", viewCount))), /*#__PURE__*/React.createElement(designSystem.Button, {
131
+ variant: "cta",
132
+ prefix: "math-plus",
133
+ style: toggleStyles,
134
+ onClick: onToggle
135
+ }));
136
+ };
137
+
138
+ const useAppSettings = () => React$1.useContext(AppContext);
139
+ function defaultAppSettings() {
140
+ return {
141
+ workspaceId: undefined,
142
+ defaultLanguage: undefined,
143
+ supportedLanguages: [],
144
+ theme: undefined,
145
+ themes: undefined,
146
+ routes: [],
147
+ initialEntries: [],
148
+ initialIndex: 0,
149
+ router: 'browser',
150
+ gaId: undefined,
151
+ apiUrl: undefined,
152
+ devMode: false
153
+ };
154
+ }
155
+
156
+ const AppContext = /*#__PURE__*/React$1.createContext(defaultAppSettings());
157
+ const App = _appSettings => {
158
+ const appSettings = {
159
+ ...defaultAppSettings(),
160
+ ..._appSettings
161
+ };
162
+ const sdk$1 = sdk.SDK.of({
163
+ apiUrl: appSettings.apiUrl,
164
+ workspaceId: appSettings.workspaceId
165
+ });
166
+ return /*#__PURE__*/React$1.createElement(AppContext.Provider, {
167
+ value: appSettings
168
+ }, /*#__PURE__*/React$1.createElement(designSystem.Theme, {
169
+ theme: appSettings.theme,
170
+ themes: appSettings.themes
171
+ }, /*#__PURE__*/React$1.createElement(sdkReact.WorkspaceProvider, {
172
+ sdk: sdk$1
173
+ }, /*#__PURE__*/React$1.createElement(routerReact.Router, _appSettings), appSettings.devMode && /*#__PURE__*/React$1.createElement(ThemeEditor, null))));
174
+ };
175
+
176
+ function _extends() {
177
+ return _extends = Object.assign ? Object.assign.bind() : function (n) {
178
+ for (var e = 1; e < arguments.length; e++) {
179
+ var t = arguments[e];
180
+ for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]);
181
+ }
182
+ return n;
183
+ }, _extends.apply(null, arguments);
184
+ }
185
+
186
+ const Layout = ({
187
+ layoutId,
188
+ ...props
189
+ }) => {
190
+ const {
191
+ status,
192
+ resource
193
+ } = sdkReact.useResource(layoutId);
194
+ const layoutStyles = React$1.useMemo(() => !resource.data ? {} : {
195
+ display: 'grid',
196
+ gridTemplateRows: resource.data.rows,
197
+ gridTemplateColumns: resource.data.columns,
198
+ gridTemplateAreas: resource.data.areas
199
+ }, [resource]);
200
+ return status === sdkReact.AsyncStatus.Success ? /*#__PURE__*/React.createElement("div", _extends({}, props, {
201
+ style: layoutStyles
202
+ })) : /*#__PURE__*/React.createElement(React.Fragment, null);
203
+ };
204
+
205
+ // https://twitter.com/jh3yy/status/1762979019446698310
206
+ // button:hover span:after {
207
+ // animation: flip 0.2s calc(var(--i) * 0.05s);
208
+ // }
209
+ // @​keyframes flip {
210
+ // 20% { content: '_'; }
211
+ // 40% { content: var(--c1); }
212
+ // 60% { content: var(--c2); }
213
+ // }
214
+
215
+ // <button>
216
+ // <span style="--i: 0; --c1: 'x'; --c2: '$'; --c3: '≈';">C</span>
217
+ // <span style="--i: 1; --c1: 'ç'; --c2: '&'; --c3: 'π';">l</span>
218
+ // <!-- Other characters -->
219
+ // <span class="sr-only">Click Me</span>
220
+ // </button>
221
+
222
+ const Ossybot = ({
223
+ style = {},
224
+ surface = "cta",
225
+ icon,
226
+ ...props
227
+ }) => {
228
+ return /*#__PURE__*/React$1.createElement(React$1.Fragment, null, /*#__PURE__*/React$1.createElement("style", {
229
+ href: "@ossy/design-system/ossybot",
230
+ precedence: "high"
231
+ }, `
232
+ @keyframes flip {
233
+ 0% {
234
+ content: '_';
235
+ }
236
+ 60% {
237
+ content: var(--c1);
238
+ }
239
+ 100% {
240
+ content: var(--c2);
241
+ }
242
+ }
243
+
244
+ /* Define the animation */
245
+ [data-animation="flip"] {
246
+ animation: flip 0.2s calc(var(--i) * 0.05s) infinite;
247
+ }
248
+ `), /*#__PURE__*/React$1.createElement(designSystem.Button, _extends({
249
+ "data-animation": "flip",
250
+ prefix: {
251
+ name: icon,
252
+ size: 'm'
253
+ },
254
+ variant: surface
255
+ }, props, {
256
+ style: {
257
+ '--size': '64px',
258
+ width: 'var(--size)',
259
+ height: 'var(--size)',
260
+ padding: 'var(--space-m)',
261
+ borderRadius: '999px',
262
+ ...style
263
+ }
264
+ })));
265
+ };
266
+
267
+ const appendSlash = string => string[string.length - 1] === '/' ? string : `${string}/`;
268
+ const prependSlash = string => string[0] === '/' ? string : `/${string}`;
269
+ const padWithSlash = string => appendSlash(prependSlash(string));
270
+ const Predicates = {
271
+ byLength: desiredLength => route => {
272
+ const routeParts = route.split('/').filter(x => !!x);
273
+ return routeParts.length === desiredLength;
274
+ },
275
+ byParamPlaceHolders: activePathname => route => {
276
+ const routeParts = route.split('/').filter(x => !!x).reduce((parts, part) => part.startsWith(':') ? [...parts, '.+?'] : [...parts, part], []).join('/');
277
+ const regex = new RegExp(`^${padWithSlash(routeParts)}$`);
278
+ const passes = regex.test(activePathname);
279
+ return passes;
280
+ }
281
+ };
282
+ const useActivePageLocation = path => {
283
+ console.log('useActivePageLocation path', path);
284
+ const {
285
+ routes: pages
286
+ } = useAppSettings();
287
+ if (!path) return;
288
+
289
+ // TODO: this needs tests because I don't think it works right
290
+ const activePathname = path === '' ? '/' : padWithSlash(path);
291
+ const registeredPageRoutes = pages.map(page => padWithSlash(page.path));
292
+ const exactRouteMatch = registeredPageRoutes.find(route => route === activePathname);
293
+ let activePageLocation;
294
+ if (!!exactRouteMatch) {
295
+ activePageLocation = exactRouteMatch;
296
+ } else {
297
+ const activePathnameParts = activePathname.split('/').filter(x => !!x);
298
+ const dynamicRouteMatch = registeredPageRoutes.find(route => Predicates.byLength(activePathnameParts.length)(route) && Predicates.byParamPlaceHolders(activePathname)(route));
299
+ activePageLocation = dynamicRouteMatch;
300
+ }
301
+ console.log('useActivePageLocation exactRouteMatch', exactRouteMatch);
302
+ console.log('useActivePageLocation activePageLocation', activePageLocation);
303
+ return activePageLocation;
304
+ };
305
+
306
+ // import { useParams } from '../use-params'
307
+ // import { AppHeader } from './AppHeader'
308
+ // import { AppFooter } from './AppFooter'
309
+ // import { AccentBorder } from './AccentBorder'
310
+ // import { ContactUsContent } from './ContactUsContent'
311
+ // import { ResourcesContent } from './ResourcesContent'
312
+ // import { ResourceContent } from './ResourceContent'
313
+ // import { HomeHero } from './HomeHero'
314
+ // import { HomeContent } from './HomeContent'
315
+ // import { ConsultantsContent } from './ConsultantsContent'
316
+ // import { CommandBar } from './CommandBar'
317
+ // import { ConsultantPage } from './ConsultantPage'
318
+
319
+ const components = {
320
+ // AppHeader: AppHeader,
321
+ // AppFooter: AppFooter,
322
+ // CommandBar: CommandBar,
323
+ // AccentBorder: AccentBorder,
324
+ // HomeHero: HomeHero,
325
+ // HomeContent: HomeContent,
326
+ // ContactUsContent: ContactUsContent,
327
+ // ConsultantsContent: ConsultantsContent,
328
+ // ResourcesContent: ResourcesContent,
329
+ // ResourceContent: ResourceContent,
330
+ // ConsultantContent: ConsultantPage
331
+ };
332
+ const Section = ({
333
+ slotName,
334
+ componentId,
335
+ componentProps: pageSpecificProps = ''
336
+ }) => {
337
+ const params = useParams();
338
+ const Component = components[componentId] || (() => /*#__PURE__*/React.createElement(React.Fragment, null, "No component found"));
339
+ const [componentProps, setComponentProps] = React$1.useState({});
340
+ const {
341
+ status: defaultPropsStatus,
342
+ resources: defaultPropsQuery
343
+ } = sdkReact.useQuery({
344
+ location: `/design-system/${componentId}/`,
345
+ name: 'default',
346
+ type: '7Bb2zDh2EK65rV_0XHo_W'
347
+ });
348
+ const {
349
+ status: languageSpecificPropsStatus,
350
+ resources: languageSpecificPropsQuery
351
+ } = sdkReact.useQuery({
352
+ location: `/design-system/${componentId}/`,
353
+ name: params.marketCode,
354
+ type: '7Bb2zDh2EK65rV_0XHo_W'
355
+ });
356
+ const loaded = React$1.useMemo(() => [defaultPropsStatus, languageSpecificPropsStatus].every(status => status === sdkReact.AsyncStatus.Success), [defaultPropsStatus, languageSpecificPropsStatus]);
357
+ const slotStyles = React$1.useMemo(() => ({
358
+ gridArea: slotName
359
+ }), [slotName]);
360
+ React$1.useEffect(() => {
361
+ let props = {};
362
+ if (!!defaultPropsQuery.length && !!defaultPropsQuery[0].data.props) {
363
+ const parsedProps = JSON.parse(defaultPropsQuery[0].data.props);
364
+ props = {
365
+ ...props,
366
+ ...parsedProps
367
+ };
368
+ }
369
+ if (!!languageSpecificPropsQuery.length && !!languageSpecificPropsQuery[0].data.props) {
370
+ const parsedProps = JSON.parse(languageSpecificPropsQuery[0].data.props);
371
+ props = {
372
+ ...props,
373
+ ...parsedProps
374
+ };
375
+ }
376
+ if (!!pageSpecificProps) {
377
+ const parsedProps = JSON.parse(pageSpecificProps);
378
+ props = {
379
+ ...props,
380
+ ...parsedProps
381
+ };
382
+ }
383
+ setComponentProps(props);
384
+ }, [pageSpecificProps, defaultPropsQuery, languageSpecificPropsQuery]);
385
+ return /*#__PURE__*/React.createElement("div", {
386
+ style: slotStyles
387
+ }, loaded && /*#__PURE__*/React.createElement(Component, componentProps));
388
+ };
389
+
390
+ const Page = () => {
391
+ const activePageLocation = useActivePageLocation();
392
+ const {
393
+ resources: folder
394
+ } = sdkReact.useResources(`/pages${activePageLocation}`);
395
+ const pageSettings = folder.find(entry => entry.name === 'Page settings');
396
+ const sections = folder.filter(entry => entry.name.endsWith('Section'));
397
+ pageSettings?.data?.title;
398
+ pageSettings?.data?.layout;
399
+ if (!pageSettings) return;
400
+ setSections(sections);
401
+ return !!pageSettings && /*#__PURE__*/React.createElement(Layout, {
402
+ layoutId: pageSettings.layout
403
+ }, sections.map(section => /*#__PURE__*/React.createElement(Section, {
404
+ key: section.data.slotName,
405
+ slotName: section.data.slotName,
406
+ componentId: section.data.componentId,
407
+ componentProps: section.data.componentProps
408
+ })));
409
+ };
410
+
411
+ const getLoadingPageSettings = () => ({
412
+ title: 'Loading...'
413
+ });
414
+ const getErrorPageSettings = () => ({
415
+ title: 'Error'
416
+ });
417
+ const getNotFoundPageSettings = () => ({
418
+ title: 'Not found'
419
+ });
420
+ const getDefaultPageSettings = () => ({
421
+ title: undefined
422
+ });
423
+ const PageStatus = {
424
+ Loading: 'Loading',
425
+ Error: 'Error',
426
+ Success: 'Success',
427
+ NotFound: 'NotFound'
428
+ };
429
+ const PageDataLoader = ({
430
+ children
431
+ }) => {
432
+ const activePageLocation = useActivePageLocation();
433
+ const {
434
+ status,
435
+ resources: folder
436
+ } = sdkReact.useResources(`/pages${activePageLocation}`);
437
+ const [pageStatus, setPageStatus] = React$1.useState(PageStatus.Loading);
438
+ const [pageSettings, setPageSettings] = React$1.useState(getLoadingPageSettings());
439
+ designSystem.useDocumentTitle(pageSettings.title);
440
+ React$1.useEffect(() => {
441
+ if ([sdkReact.AsyncStatus.NotInitialized, sdkReact.AsyncStatus.Loading].includes(status)) {
442
+ setPageSettings(getLoadingPageSettings());
443
+ return setPageStatus(PageStatus.Loading);
444
+ } else if ([sdkReact.AsyncStatus.Error].includes(status)) {
445
+ setPageSettings(getErrorPageSettings());
446
+ return setPageStatus(PageStatus.Error);
447
+ } else if ([sdkReact.AsyncStatus.Success].includes(status)) {
448
+ const pageSettings = folder.find(entry => entry.name === 'Page settings');
449
+ if (!pageSettings) {
450
+ setPageSettings(getNotFoundPageSettings());
451
+ return setPageStatus(PageStatus.NotFound);
452
+ }
453
+ setPageSettings({
454
+ title: pageSettings.data.title,
455
+ layout: pageSettings.data.layout,
456
+ slots: pageSettings.data.slots
457
+ });
458
+ setPageStatus(PageStatus.Success);
459
+ }
460
+ return () => {
461
+ setPageSettings(getDefaultPageSettings());
462
+ };
463
+ }, [status, folder]);
464
+ return /*#__PURE__*/React.createElement(designSystem.Switch, {
465
+ on: pageStatus
466
+ }, /*#__PURE__*/React.createElement(designSystem.Switch.Case, {
467
+ match: [PageStatus.NotFound]
468
+ }, "Page not found"), /*#__PURE__*/React.createElement(designSystem.Switch.Case, {
469
+ match: [PageStatus.Error]
470
+ }, "Couldn't load the page"), /*#__PURE__*/React.createElement(designSystem.Switch.Case, {
471
+ match: [PageStatus.Loading]
472
+ }, "Page Loading"), /*#__PURE__*/React.createElement(designSystem.Switch.Case, {
473
+ match: [PageStatus.Success]
474
+ }, children));
475
+ };
476
+
477
+ const PagesModule = () => /*#__PURE__*/React.createElement(PageDataLoader, null, /*#__PURE__*/React.createElement(Page, null));
478
+
479
+ const translations = {
480
+ en: {
481
+ tags: 'Experience with',
482
+ work: 'Work',
483
+ projects: 'Projects',
484
+ education: 'Education',
485
+ other: 'Other',
486
+ download: 'Download',
487
+ all: 'All'
488
+ }
489
+ };
490
+ const getProfile = resources => {
491
+ const image = resources?.find(x => x.type.startsWith('image/'));
492
+ const {
493
+ id,
494
+ content
495
+ } = resources?.find(x => x.type === 'resume-summary') || {
496
+ content: {}
497
+ };
498
+ const profile = {
499
+ id: id,
500
+ name: content.Name || content['Consultant Name'],
501
+ role: content.Role,
502
+ image: image?.content?.src,
503
+ summary: content.Summary,
504
+ tags: content?.Tags?.split(','),
505
+ links: []
506
+ };
507
+ content.Mobile && profile.links.push({
508
+ icon: 'phone',
509
+ label: content.Mobile,
510
+ href: `tel:${content.Mobile}`,
511
+ target: '_blank'
512
+ });
513
+ content.Email && profile.links.push({
514
+ icon: 'mail',
515
+ label: content.Email,
516
+ href: `mailto:${content.Email}`
517
+ });
518
+ content.Website && profile.links.push({
519
+ icon: 'globe-alt',
520
+ label: content.Website.replace('https://', '').replace('http://', ''),
521
+ href: content.Website,
522
+ target: '_blank'
523
+ });
524
+ return profile;
525
+ };
526
+ const getExperiences = resources => resources.filter(x => x.type === 'resume-experience').map(resource => ({
527
+ id: resource.id,
528
+ title: resource.content.Title,
529
+ subTitle: resource.content['Sub Title'],
530
+ date: resource.content.Date,
531
+ description: resource.content.Description,
532
+ website: resource.content.Website,
533
+ github: resource.content.GitHub,
534
+ tags: resource.content?.Tags?.split(',')?.map(x => x.trim()).filter(x => !!x),
535
+ typeOfExperience: resource.content['Type of experience']
536
+ }));
537
+ const useMergeAsyncStatus = (...statuses) => {
538
+ return statuses.reduce((acc, status) => {
539
+ if (acc === 'Loading' || status === 'Loading' || status === 'NotInitialized') {
540
+ return 'Loading';
541
+ }
542
+ if (acc === 'Error' || status === 'Error') {
543
+ return 'Error';
544
+ }
545
+ if (acc === 'AuthenticationError' || status === 'AuthenticationError') {
546
+ return 'AuthenticationError';
547
+ }
548
+ return 'Success';
549
+ }, 'NotInitialized');
550
+ };
551
+ const location = '/@ossy/resumes/';
552
+ const useResume = resumeId => {
553
+ const resumeDirectory = sdkReact.useResource(resumeId);
554
+ const resumeResources = sdkReact.useResources(resumeDirectory?.resource?.name ? location + resumeDirectory?.resource?.name + '/' : undefined);
555
+ const status = useMergeAsyncStatus(resumeDirectory.status, resumeResources.status);
556
+ return {
557
+ status,
558
+ translations: translations.en,
559
+ profile: getProfile(resumeResources.resources),
560
+ experiences: getExperiences(resumeResources.resources)
561
+ };
562
+ };
563
+
564
+ const Resume = ({
565
+ resumeId,
566
+ ...props
567
+ }) => {
568
+ const resumeProps = useResume(resumeId);
569
+ return resumeProps.status === 'Success' ? /*#__PURE__*/React$1.createElement(designSystemExtras.Resume, _extends({}, resumeProps, {
570
+ profileCardVariant: "resume"
571
+ }, props)) : /*#__PURE__*/React$1.createElement(React$1.Fragment, null);
572
+ };
573
+
574
+ const ResumeTemplates = [{
575
+ name: 'Resume Experience',
576
+ id: 'resume-experience',
577
+ fields: [{
578
+ name: 'Title',
579
+ type: 'text'
580
+ }, {
581
+ name: 'Sub Title',
582
+ type: 'text'
583
+ }, {
584
+ name: 'Date',
585
+ type: 'text'
586
+ }, {
587
+ name: 'Description',
588
+ type: 'textarea'
589
+ }, {
590
+ name: 'Type of experience',
591
+ type: 'select',
592
+ options: ['Work', 'Education', 'Other', 'Project']
593
+ }, {
594
+ name: 'Website',
595
+ type: 'text'
596
+ }, {
597
+ name: 'Tags',
598
+ type: 'text'
599
+ }, {
600
+ name: 'GitHub',
601
+ type: 'text'
602
+ }]
603
+ }, {
604
+ name: 'Resume Summary',
605
+ id: 'resume-summary',
606
+ fields: [{
607
+ name: 'Name',
608
+ type: 'text'
609
+ }, {
610
+ name: 'Role',
611
+ type: 'text'
612
+ }, {
613
+ name: 'Summary',
614
+ type: 'textarea'
615
+ }, {
616
+ name: 'Mobile',
617
+ type: 'text'
618
+ }, {
619
+ name: 'Email',
620
+ type: 'text'
621
+ }, {
622
+ name: 'Website',
623
+ type: 'text'
624
+ }, {
625
+ name: 'Tags',
626
+ type: 'textarea'
627
+ }]
628
+ }];
629
+
630
+ const ThemeProvider = props => {
631
+ const {
632
+ status,
633
+ resource: theme
634
+ } = sdkReact.useResource('PCX53TaGviq4_8KvK-VOp');
635
+ return status === sdkReact.AsyncStatus.Success ? /*#__PURE__*/React.createElement(designSystem.Theme, _extends({
636
+ theme: theme.data
637
+ }, props)) : /*#__PURE__*/React.createElement(React.Fragment, null);
638
+ };
639
+
640
+ exports.App = App;
641
+ exports.AppContext = AppContext;
642
+ exports.Layout = Layout;
643
+ exports.Ossybot = Ossybot;
644
+ exports.Page = Page;
645
+ exports.PageDataLoader = PageDataLoader;
646
+ exports.PagesModule = PagesModule;
647
+ exports.Resume = Resume;
648
+ exports.ResumeTemplates = ResumeTemplates;
649
+ exports.ThemeEditor = ThemeEditor;
650
+ exports.ThemeProvider = ThemeProvider;
651
+ exports.defaultAppSettings = defaultAppSettings;
652
+ exports.location = location;
653
+ exports.useActivePageLocation = useActivePageLocation;
654
+ exports.useAppSettings = useAppSettings;
655
+ exports.useMergeAsyncStatus = useMergeAsyncStatus;
656
+ exports.useResume = useResume;