@startinblox/components-ds4go 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (56) hide show
  1. package/.gitlab-ci.yml +57 -0
  2. package/.storybook/main.ts +17 -0
  3. package/.storybook/preview-head.html +8 -0
  4. package/.storybook/preview.ts +22 -0
  5. package/LICENSE +21 -0
  6. package/README.md +129 -0
  7. package/biome.json +50 -0
  8. package/cypress/component/solid-boilerplate.cy.ts +9 -0
  9. package/cypress/support/component-index.html +12 -0
  10. package/cypress/support/component.ts +17 -0
  11. package/cypress.config.ts +11 -0
  12. package/dist/components-ds4go.css +1 -0
  13. package/dist/index.js +1634 -0
  14. package/lit-localize.json +15 -0
  15. package/locales/en.xlf +28 -0
  16. package/package.json +93 -0
  17. package/postcss.config.js +8 -0
  18. package/src/component.d.ts +167 -0
  19. package/src/components/catalog/ds4go-fact-bundle-holder.ts +162 -0
  20. package/src/components/modal/ds4go-fact-bundle-modal.ts +82 -0
  21. package/src/components/solid-fact-bundle.ts +225 -0
  22. package/src/context.json +1 -0
  23. package/src/helpers/components/ResourceMapper.ts +450 -0
  24. package/src/helpers/components/componentObjectHandler.ts +22 -0
  25. package/src/helpers/components/componentObjectsHandler.ts +14 -0
  26. package/src/helpers/components/dspComponent.ts +243 -0
  27. package/src/helpers/components/orbitComponent.ts +273 -0
  28. package/src/helpers/components/setupCacheInvalidation.ts +44 -0
  29. package/src/helpers/components/setupCacheOnResourceReady.ts +39 -0
  30. package/src/helpers/components/setupComponentSubscriptions.ts +73 -0
  31. package/src/helpers/components/setupOnSaveReset.ts +20 -0
  32. package/src/helpers/datas/dataBuilder.ts +43 -0
  33. package/src/helpers/datas/filterGenerator.ts +29 -0
  34. package/src/helpers/datas/filterObjectByDateAfter.ts +80 -0
  35. package/src/helpers/datas/filterObjectById.ts +54 -0
  36. package/src/helpers/datas/filterObjectByInterval.ts +133 -0
  37. package/src/helpers/datas/filterObjectByNamedValue.ts +103 -0
  38. package/src/helpers/datas/filterObjectByType.ts +30 -0
  39. package/src/helpers/datas/filterObjectByValue.ts +81 -0
  40. package/src/helpers/datas/sort.ts +40 -0
  41. package/src/helpers/i18n/configureLocalization.ts +17 -0
  42. package/src/helpers/index.ts +43 -0
  43. package/src/helpers/mappings/dsp-mapping-config.ts +545 -0
  44. package/src/helpers/ui/formatDate.ts +18 -0
  45. package/src/helpers/ui/lipsum.ts +12 -0
  46. package/src/helpers/utils/requestNavigation.ts +12 -0
  47. package/src/helpers/utils/uniq.ts +6 -0
  48. package/src/index.ts +14 -0
  49. package/src/initializer.ts +11 -0
  50. package/src/mocks/orbit.mock.ts +33 -0
  51. package/src/mocks/user.mock.ts +67 -0
  52. package/src/styles/_helpers/flex.scss +39 -0
  53. package/src/styles/index.scss +14 -0
  54. package/src/styles/modal/ds4go-fact-bundle-modal.scss +89 -0
  55. package/tsconfig.json +36 -0
  56. package/vite.config.ts +48 -0
@@ -0,0 +1,15 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/lit/lit/main/packages/localize-tools/config.schema.json",
3
+ "sourceLocale": "en",
4
+ "targetLocales": ["en"],
5
+ "tsConfig": "./tsconfig.json",
6
+ "output": {
7
+ "mode": "runtime",
8
+ "outputDir": "./src/generated/locales",
9
+ "localeCodesModule": "./src/generated/locale-codes.ts"
10
+ },
11
+ "interchange": {
12
+ "format": "xliff",
13
+ "xliffDir": "./locales/"
14
+ }
15
+ }
package/locales/en.xlf ADDED
@@ -0,0 +1,28 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">
3
+ <file target-language="en" source-language="en" original="lit-localize-inputs" datatype="plaintext">
4
+ <body>
5
+ <trans-unit id="sf5509a9f253b9836">
6
+ <source>Create a bundle</source>
7
+ </trans-unit>
8
+ <trans-unit id="sefa717c1620c4ae4">
9
+ <source>facts</source>
10
+ </trans-unit>
11
+ <trans-unit id="sef234a791696afff">
12
+ <source>fact</source>
13
+ </trans-unit>
14
+ <trans-unit id="s4979bd417e7c8052">
15
+ <source>All facts in this bundle</source>
16
+ </trans-unit>
17
+ <trans-unit id="s0d1be7a2c400c080">
18
+ <source>more</source>
19
+ </trans-unit>
20
+ <trans-unit id="s57a40de45f324b96">
21
+ <source>Bundle created on</source>
22
+ </trans-unit>
23
+ <trans-unit id="sd3682395cf86f913">
24
+ <source>Bundle updated on</source>
25
+ </trans-unit>
26
+ </body>
27
+ </file>
28
+ </xliff>
package/package.json ADDED
@@ -0,0 +1,93 @@
1
+ {
2
+ "name": "@startinblox/components-ds4go",
3
+ "version": "1.0.0",
4
+ "description": "Startin'blox DS4GO",
5
+ "main": "dist/index.js",
6
+ "type": "module",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://git.startinblox.com/components/solid-ds4go.git"
10
+ },
11
+ "author": "startinblox",
12
+ "license": "MIT",
13
+ "release": {
14
+ "branches": [
15
+ "master",
16
+ {
17
+ "name": "beta",
18
+ "prerelease": true
19
+ },
20
+ {
21
+ "name": "alpha",
22
+ "prerelease": true
23
+ }
24
+ ],
25
+ "plugins": [
26
+ [
27
+ "@semantic-release/commit-analyzer",
28
+ {
29
+ "preset": "angular",
30
+ "releaseRules": [
31
+ {
32
+ "type": "major",
33
+ "release": "major"
34
+ },
35
+ {
36
+ "type": "minor",
37
+ "release": "minor"
38
+ },
39
+ {
40
+ "type": "*",
41
+ "release": "patch"
42
+ }
43
+ ]
44
+ }
45
+ ],
46
+ "@semantic-release/release-notes-generator",
47
+ "@semantic-release/gitlab",
48
+ "@semantic-release/npm"
49
+ ]
50
+ },
51
+ "publishConfig": {
52
+ "access": "public"
53
+ },
54
+ "scripts": {
55
+ "watch": "lit-localize build && vite",
56
+ "build": "lit-localize build && vite build",
57
+ "serve": "vite preview",
58
+ "cy:open": "cypress open --component",
59
+ "cy:run": "lit-localize build && cypress run --component",
60
+ "storybook": "lit-localize build && storybook dev -p 6006",
61
+ "build-storybook": "lit-localize build && storybook build",
62
+ "locale:extract": "lit-localize extract",
63
+ "locale:build": "lit-localize build"
64
+ },
65
+ "browserslist": [
66
+ "last 2 Chrome versions"
67
+ ],
68
+ "dependencies": {
69
+ "@lit/localize": "^0.12.2",
70
+ "@lit/task": "^1.0.3",
71
+ "autoprefixer": "^10.4.21",
72
+ "cssnano": "^7.1.1",
73
+ "lit": "^3.3.1",
74
+ "postcss": "^8.5.6",
75
+ "postcss-preset-env": "^10.4.0",
76
+ "postcss-scss": "^4.0.9",
77
+ "sass": "^1.93.2",
78
+ "unplugin-icons": "^22.5.0",
79
+ "vite": "^7.1.12"
80
+ },
81
+ "devDependencies": {
82
+ "@lit/localize-tools": "^0.8.0",
83
+ "@storybook/addon-docs": "^9.1.13",
84
+ "@storybook/web-components-vite": "^9.1.13",
85
+ "baseline-browser-mapping": "^2.9.19",
86
+ "buffer": "^6.0.3",
87
+ "cypress": "^15.5.0",
88
+ "cypress-ct-lit": "^1.0.0",
89
+ "lorem-ipsum": "^2.0.8",
90
+ "storybook": "^9.1.13",
91
+ "stream-browserify": "^3.0.0"
92
+ }
93
+ }
@@ -0,0 +1,8 @@
1
+ import autoprefixer from "autoprefixer";
2
+ import cssnano from "cssnano";
3
+ import postcssPresetEnv from "postcss-preset-env";
4
+
5
+ export default {
6
+ syntax: "postcss-scss",
7
+ plugins: [autoprefixer, cssnano, postcssPresetEnv],
8
+ };
@@ -0,0 +1,167 @@
1
+ /// <reference types="vite/client" />
2
+ /// <reference types="unplugin-icons/types/raw" />
3
+ /// <reference types="unplugin-icons/types/web-components" />
4
+
5
+ import type { TemplateResult } from "lit";
6
+
7
+ interface PWAIcons {
8
+ src: string;
9
+ sizes: string;
10
+ type: string;
11
+ purpose: string;
12
+ }
13
+
14
+ interface PWA {
15
+ dir: string;
16
+ icons: PWAIcons[];
17
+ start_url: string;
18
+ display: string;
19
+ orientation: string;
20
+ background_color: string;
21
+ theme_color: string;
22
+ }
23
+
24
+ interface I18n {
25
+ lang: string;
26
+ force: boolean;
27
+ }
28
+
29
+ interface ComponentParameters {
30
+ replacement?: string;
31
+ bindResources?: string;
32
+ bindUser?: string;
33
+ dataSrc?: string;
34
+ nestedField?: string;
35
+ authority?: string;
36
+ authorityName?: string;
37
+ noRender?: string;
38
+ }
39
+
40
+ interface OrbitComponent {
41
+ type?: string;
42
+ parameters: ComponentParameters;
43
+ route: string | false;
44
+ integration?: string[];
45
+ uniq?: string;
46
+ experimental?: string[];
47
+ routeAttributes?: {
48
+ "rdf-type": string;
49
+ "use-id": string;
50
+ };
51
+ defaultRoute?: boolean;
52
+ extensions?: OrbitComponent[];
53
+ attributes?: Record<string, any>;
54
+ instance?: Element;
55
+ }
56
+
57
+ interface OrbitClient {
58
+ name: string;
59
+ logo: string;
60
+ server?: string;
61
+ css?: string[] | string | false;
62
+ description?: string;
63
+ favicon?: string;
64
+ defaultAvatar?: string;
65
+ i18n?: I18n;
66
+ pwa?: PWA;
67
+ }
68
+
69
+ interface NpmPackage {
70
+ package: string;
71
+ version: string;
72
+ path: string;
73
+ }
74
+
75
+ export interface Orbit {
76
+ client: OrbitClient;
77
+ components: OrbitComponent[];
78
+ npm?: NpmPackage[];
79
+ }
80
+
81
+ export interface LiveOrbit extends Orbit {
82
+ componentSet: Set<string>;
83
+ federations: Record<string, any>;
84
+ getDefaultRoute: () => string;
85
+ getComponent: (type: string) => OrbitComponent | undefined;
86
+ getComponentFromRoute: (route: string) => OrbitComponent | undefined;
87
+ getRoute: (
88
+ type: string,
89
+ returnFirst?: boolean,
90
+ ignoreError?: boolean
91
+ ) => string | false;
92
+ Swal: any;
93
+ defaultRoute: string;
94
+ }
95
+
96
+ export type Context = Record<string, string | { "@id": string }>;
97
+ export type Permission = "add" | "delete" | "change" | "control" | "view" | string;
98
+ export type DateTime = string;
99
+
100
+ export interface LimitedResource {
101
+ "@id": string;
102
+ "@type"?: string | string[] | Promise<string | string[]>;
103
+ _originalResource?: Resource;
104
+ properties?: string[] | Promise<string[]>;
105
+ permissions?: Permission[];
106
+ clientContext?: Context | Promise<Context>;
107
+ serverContext?: Context | Promise<Context>;
108
+ }
109
+
110
+ export interface Resource extends LimitedResource {
111
+ [key: string]: any;
112
+ }
113
+
114
+ export interface UnknownResource {
115
+ [key: string]: any;
116
+ }
117
+
118
+ interface Container<T> extends Resource {
119
+ "ldp:contains": T[];
120
+ }
121
+
122
+ type ProxyValue<T> = T extends Array<infer U> ? U[] : Resource & T;
123
+
124
+ export interface User extends Resource {
125
+ account?: Account;
126
+ first_name?: string;
127
+ last_name?: string;
128
+ name?: string;
129
+ username?: string;
130
+ email?: string;
131
+ }
132
+
133
+ export interface Account extends Resource {
134
+ picture?: string | null;
135
+ }
136
+
137
+ export interface PropertiesPicker {
138
+ key: string;
139
+ value: string;
140
+ cast?: function;
141
+ expand?: boolean;
142
+ }
143
+
144
+ export type TemplateResultOrSymbol = TemplateResult | symbol;
145
+
146
+ export interface SearchObject {
147
+ name: string;
148
+ value: string;
149
+ type?: string;
150
+ }
151
+
152
+ export declare global {
153
+ interface Window {
154
+ orbit: LiveOrbit;
155
+ sibStore: { getData: ProxyValue<Resource | Container>; [key: string]: any };
156
+ sibRouter: { [key: string]: any };
157
+ }
158
+ interface Element {
159
+ currentRouteName: string;
160
+ }
161
+ interface Event {
162
+ [key: string]: any;
163
+ }
164
+ interface EventTarget {
165
+ [key: string]: any;
166
+ }
167
+ }
@@ -0,0 +1,162 @@
1
+ import {
2
+ ComponentObjectsHandler,
3
+ filterObjectByDateAfter,
4
+ filterObjectById,
5
+ filterObjectByInterval,
6
+ filterObjectByNamedValue,
7
+ filterObjectByType,
8
+ filterObjectByValue,
9
+ } from "@helpers";
10
+ import { msg } from "@lit/localize";
11
+ import type { Resource, SearchObject } from "@src/component";
12
+ import { css, html, nothing, type PropertyValues } from "lit";
13
+ import { customElement, state } from "lit/decorators.js";
14
+
15
+ @customElement("ds4go-fact-bundle-holder")
16
+ export class Ds4goFactBundleHolder extends ComponentObjectsHandler {
17
+ static styles = css`
18
+ .card-grid {
19
+ display: flex;
20
+ flex-direction: row;
21
+ flex-wrap: wrap;
22
+ gap: 20px;
23
+ }
24
+ .card-grid-vertical {
25
+ justify-content: stretch;
26
+ }
27
+ .card-grid-vertical tems-card-catalog {
28
+ width: 354px;
29
+ height: auto;
30
+ }
31
+ tems-card-catalog {
32
+ cursor: pointer;
33
+ }
34
+ `;
35
+
36
+ @state()
37
+ search: SearchObject[] = [];
38
+
39
+ @state()
40
+ protected _displayObjects: Resource[] = [];
41
+
42
+ protected filter(objects: Resource[], filters: SearchObject[] = []) {
43
+ if (!filters || filters.length === 0 || !objects || objects.length === 0) {
44
+ return objects;
45
+ }
46
+
47
+ const groupedFilters = new Map<string, SearchObject[]>();
48
+ for (const filter of filters) {
49
+ const groupKey = filter.name;
50
+ const group = groupedFilters.get(groupKey) || [];
51
+ group.push(filter);
52
+ groupedFilters.set(groupKey, group);
53
+ }
54
+
55
+ let currentFilteredObjects = [...objects];
56
+
57
+ for (const filterGroup of groupedFilters.values()) {
58
+ if (currentFilteredObjects.length === 0) {
59
+ break;
60
+ }
61
+
62
+ const tempResults = [];
63
+ for (const filter of filterGroup) {
64
+ switch (filter.type) {
65
+ case "interval":
66
+ tempResults.push(
67
+ filterObjectByInterval(
68
+ currentFilteredObjects,
69
+ filter.name,
70
+ filter.value,
71
+ ),
72
+ );
73
+ break;
74
+ case "dateAfter":
75
+ tempResults.push(
76
+ filterObjectByDateAfter(
77
+ currentFilteredObjects,
78
+ filter.name,
79
+ filter.value,
80
+ ),
81
+ );
82
+ break;
83
+ case "matchId":
84
+ tempResults.push(
85
+ filterObjectById(
86
+ currentFilteredObjects,
87
+ filter.name,
88
+ filter.value,
89
+ ),
90
+ );
91
+ break;
92
+ case "matchType":
93
+ tempResults.push(
94
+ filterObjectByType(currentFilteredObjects, filter.value),
95
+ );
96
+ break;
97
+ case "exact":
98
+ tempResults.push(
99
+ filterObjectByNamedValue(
100
+ currentFilteredObjects,
101
+ filter.name,
102
+ filter.value,
103
+ ),
104
+ );
105
+ break;
106
+ default:
107
+ tempResults.push(
108
+ filterObjectByValue(currentFilteredObjects, filter.value),
109
+ );
110
+ }
111
+ }
112
+ currentFilteredObjects = [...tempResults.flat()];
113
+ }
114
+
115
+ return currentFilteredObjects;
116
+ }
117
+
118
+ protected _handleClickEvent(originalObj: Resource) {
119
+ this.dispatchEvent(new CustomEvent("clicked", { detail: originalObj }));
120
+ }
121
+
122
+ willUpdate(changedProperties: PropertyValues) {
123
+ if (changedProperties.has("objects") || changedProperties.has("search")) {
124
+ if (this.objects) {
125
+ this._displayObjects = this.filter(this.objects, this.search);
126
+ } else {
127
+ this._displayObjects = [];
128
+ }
129
+ this.dispatchEvent(
130
+ new CustomEvent("result-count", {
131
+ detail: this._displayObjects.length,
132
+ }),
133
+ );
134
+ }
135
+ }
136
+
137
+ render() {
138
+ if (!this._displayObjects || this._displayObjects.length === 0) {
139
+ return nothing;
140
+ }
141
+
142
+ return html`<div class="card-grid card-grid-vertical">
143
+ ${this._displayObjects.map((displayObj) => {
144
+ const tags = [
145
+ {
146
+ name: `${displayObj.facts.length} ${displayObj.facts.length > 1 ? msg("facts") : msg("fact")}`,
147
+ type: "information",
148
+ },
149
+ ];
150
+ return html`<tems-card-catalog
151
+ .object=${import.meta.env.DEV ? displayObj : nothing}
152
+ type=${"bill-image"}
153
+ .tags=${tags}
154
+ .header=${displayObj.name || nothing}
155
+ .content=${displayObj.description || nothing}
156
+ date=${displayObj.updated_at || nothing}
157
+ @click=${() => this._handleClickEvent(displayObj)}
158
+ ></tems-card-catalog>`;
159
+ })}
160
+ </div>`;
161
+ }
162
+ }
@@ -0,0 +1,82 @@
1
+ import { ComponentObjectHandler } from "@helpers";
2
+ import { localized, msg } from "@lit/localize";
3
+ import type { Resource } from "@src/component";
4
+
5
+ import ModalStyle from "@styles/modal/ds4go-fact-bundle-modal.scss?inline";
6
+ import { css, html, nothing, unsafeCSS } from "lit";
7
+ import { customElement, property } from "lit/decorators.js";
8
+
9
+ @customElement("ds4go-fact-bundle-modal")
10
+ @localized()
11
+ export class Ds4goFactBundleModal extends ComponentObjectHandler {
12
+ static styles = css`
13
+ ${unsafeCSS(ModalStyle)}
14
+ `;
15
+
16
+ @property({ attribute: false, type: Object })
17
+ object: Resource = { "@id": "" };
18
+
19
+ _closeModal() {
20
+ this.dispatchEvent(new CustomEvent("close"));
21
+ }
22
+
23
+ render() {
24
+ return html`<div class="modal">
25
+ <div class="topbar">
26
+ <tems-button
27
+ @click=${this._closeModal}
28
+ type="outline-gray"
29
+ .iconLeft=${html`<icon-material-symbols-close-rounded></icon-material-symbols-close-rounded>`}
30
+ ></tems-button>
31
+ </div>
32
+ <div class="modal-content-wrapper">
33
+ <div class="modal-box">
34
+ <div class="modal-content">
35
+ <tems-division type="h3"
36
+ ><div>${String(this.object.name)}</div></tems-division
37
+ >
38
+ <tems-division type="body-m"
39
+ ><div>${String(this.object.description)}</div></tems-division
40
+ >
41
+ <tems-division type="h4"
42
+ ><div>${msg("All facts in this bundle")}</div></tems-division
43
+ >
44
+ <div class="card-grid card-grid-vertical">
45
+ ${this.object.facts.map((fact: Resource) => {
46
+ const tags = fact.categories.map((c: Resource) => ({
47
+ name: c.name,
48
+ type: "information",
49
+ }));
50
+ if (tags.length > 3) {
51
+ const overflowTags = tags.length - 3;
52
+ tags.splice(3, overflowTags);
53
+ tags.push({
54
+ name: `+${overflowTags} ${msg("more")}`,
55
+ type: "information",
56
+ });
57
+ }
58
+ return html`<tems-card-catalog
59
+ .object=${import.meta.env.DEV ? fact : nothing}
60
+ .tags=${tags}
61
+ .header=${fact.name || nothing}
62
+ .content=${fact.description || nothing}
63
+ date=${fact.updated_at || nothing}
64
+ ></tems-card-catalog>`;
65
+ })}
66
+ </div>
67
+ <tems-division type="body-sm"
68
+ ><div>
69
+ <div>
70
+ ${msg("Bundle created on")} ${String(this.object.created_at)}
71
+ </div>
72
+ <div>
73
+ ${msg("Bundle updated on")} ${String(this.object.updated_at)}
74
+ </div>
75
+ </div></tems-division
76
+ >
77
+ </div>
78
+ </div>
79
+ </div>
80
+ </div>`;
81
+ }
82
+ }