@ossy/connected-components 0.0.10 → 0.0.15

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