@supersoniks/concorde 3.1.77 → 3.1.78
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/build-infos.json +1 -1
- package/concorde-core.bundle.js +2 -2
- package/concorde-core.es.js +2 -2
- package/dist/concorde-core.bundle.js +2 -2
- package/dist/concorde-core.es.js +2 -2
- package/docs/assets/index-D9bBwsCn.js +4537 -0
- package/docs/assets/index-DCRPZO3x.css +1 -0
- package/docs/css/docs.css +0 -0
- package/docs/fonts/ClashGrotesk-Bold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Bold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Bold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.eot +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff +0 -0
- package/docs/fonts/ClashGrotesk-Extralight.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Light.eot +0 -0
- package/docs/fonts/ClashGrotesk-Light.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff +0 -0
- package/docs/fonts/ClashGrotesk-Light.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Medium.eot +0 -0
- package/docs/fonts/ClashGrotesk-Medium.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff +0 -0
- package/docs/fonts/ClashGrotesk-Medium.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Regular.eot +0 -0
- package/docs/fonts/ClashGrotesk-Regular.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff +0 -0
- package/docs/fonts/ClashGrotesk-Regular.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.eot +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff +0 -0
- package/docs/fonts/ClashGrotesk-Semibold.woff2 +0 -0
- package/docs/fonts/ClashGrotesk-Variable.eot +0 -0
- package/docs/fonts/ClashGrotesk-Variable.ttf +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff +0 -0
- package/docs/fonts/ClashGrotesk-Variable.woff2 +0 -0
- package/docs/img/concorde-icon.svg +5 -0
- package/docs/img/concorde-logo.svg +1 -0
- package/docs/img/concorde.png +0 -0
- package/docs/img/concorde_def.png +0 -0
- package/docs/img/concorde_seuil.png.webp +0 -0
- package/docs/img/concorde_seuil_invert.png +0 -0
- package/docs/img/paul_metrand.jpg +0 -0
- package/docs/img/paul_metrand_xs.jpg +0 -0
- package/docs/index.html +93 -0
- package/docs/src/core/components/functional/date/date.md +290 -0
- package/docs/src/core/components/functional/fetch/fetch.md +117 -0
- package/docs/src/core/components/functional/if/if.md +16 -0
- package/docs/src/core/components/functional/list/list.md +199 -0
- package/docs/src/core/components/functional/mix/mix.md +41 -0
- package/docs/src/core/components/functional/queue/queue.md +87 -0
- package/docs/src/core/components/functional/router/router.md +108 -0
- package/docs/src/core/components/functional/sdui/default-library.json +108 -0
- package/docs/src/core/components/functional/sdui/example.json +99 -0
- package/docs/src/core/components/functional/sdui/sdui.md +356 -0
- package/docs/src/core/components/functional/states/states.md +87 -0
- package/docs/src/core/components/functional/submit/submit.md +83 -0
- package/docs/src/core/components/functional/subscriber/subscriber.md +91 -0
- package/docs/src/core/components/functional/value/value.md +35 -0
- package/docs/src/core/components/ui/alert/alert.md +121 -0
- package/docs/src/core/components/ui/alert-messages/alert-messages.md +0 -0
- package/docs/src/core/components/ui/badge/badge.md +127 -0
- package/docs/src/core/components/ui/button/button.md +182 -0
- package/docs/src/core/components/ui/captcha/captcha.md +12 -0
- package/docs/src/core/components/ui/card/card.md +97 -0
- package/docs/src/core/components/ui/divider/divider.md +35 -0
- package/docs/src/core/components/ui/form/checkbox/checkbox.md +94 -0
- package/docs/src/core/components/ui/form/fieldset/fieldset.md +129 -0
- package/docs/src/core/components/ui/form/form-actions/form-actions.md +77 -0
- package/docs/src/core/components/ui/form/form-layout/form-layout.md +44 -0
- package/docs/src/core/components/ui/form/input/input.md +167 -0
- package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +130 -0
- package/docs/src/core/components/ui/form/radio/radio.md +84 -0
- package/docs/src/core/components/ui/form/select/select.md +97 -0
- package/docs/src/core/components/ui/form/switch/switch.md +84 -0
- package/docs/src/core/components/ui/form/textarea/textarea.md +65 -0
- package/docs/src/core/components/ui/group/group.md +75 -0
- package/docs/src/core/components/ui/icon/icon.md +125 -0
- package/docs/src/core/components/ui/icon/icons.json +1 -0
- package/docs/src/core/components/ui/image/image.md +107 -0
- package/docs/src/core/components/ui/link/link.md +43 -0
- package/docs/src/core/components/ui/loader/loader.md +67 -0
- package/docs/src/core/components/ui/menu/menu.md +288 -0
- package/docs/src/core/components/ui/modal/modal.md +123 -0
- package/docs/src/core/components/ui/pop/pop.md +79 -0
- package/docs/src/core/components/ui/progress/progress.md +63 -0
- package/docs/src/core/components/ui/table/table.md +455 -0
- package/docs/src/core/components/ui/tooltip/tooltip.md +82 -0
- package/docs/src/docs/_core-concept/overview.md +57 -0
- package/docs/src/docs/_core-concept/subscriber.md +76 -0
- package/docs/src/docs/_getting-started/concorde-outside.md +143 -0
- package/docs/src/docs/_getting-started/create-a-component.md +137 -0
- package/docs/src/docs/_getting-started/my-first-subscriber.md +174 -0
- package/docs/src/docs/_getting-started/pubsub.md +150 -0
- package/docs/src/docs/_getting-started/start.md +39 -0
- package/docs/src/docs/_getting-started/theming.md +91 -0
- package/docs/src/docs/search/docs-search.json +3902 -0
- package/docs/src/tag-list.json +1 -0
- package/docs/src/tsconfig-model.json +23 -0
- package/docs/src/tsconfig.json +835 -0
- package/docs/svg/regular/plane.svg +1 -0
- package/docs/svg/solid/plane.svg +1 -0
- package/index.html +0 -0
- package/package.json +1 -1
- package/php/get-challenge.php +34 -0
- package/php/some-service.php +42 -0
- package/scripts/create-search.js +0 -0
- package/scripts/generate-routes.js +0 -0
- package/src/core/_types/types.ts +0 -0
- package/src/core/components/functional/date/date.ts +0 -0
- package/src/core/components/functional/functional.ts +0 -0
- package/src/core/components/functional/if/if.md +0 -0
- package/src/core/components/functional/if/if.test.ts +0 -0
- package/src/core/components/functional/list/list.demo.ts +0 -0
- package/src/core/components/functional/list/list.spec.ts +0 -0
- package/src/core/components/functional/queue/queue.demo.ts +0 -0
- package/src/core/components/functional/queue/queue.ts +1 -1
- package/src/core/components/functional/router/router.demo.ts +0 -0
- package/src/core/components/functional/router/router.md +0 -0
- package/src/core/components/functional/router/router.spec.ts +0 -0
- package/src/core/components/functional/router/router.ts +0 -0
- package/src/core/components/functional/sonic-scope/sonic-scope.ts +0 -0
- package/src/core/components/functional/states/states.demo.ts +0 -0
- package/src/core/components/functional/states/states.md +0 -0
- package/src/core/components/functional/states/states.spec.ts +0 -0
- package/src/core/components/functional/states/states.ts +0 -0
- package/src/core/components/functional/translation/translation.ts +0 -0
- package/src/core/components/ui/_css/scroll.ts +0 -0
- package/src/core/components/ui/_css/shadow.ts +0 -0
- package/src/core/components/ui/_css/size.ts +0 -0
- package/src/core/components/ui/_css/type.ts +0 -0
- package/src/core/components/ui/alert/alert.md +0 -0
- package/src/core/components/ui/alert/alert.ts +0 -0
- package/src/core/components/ui/alert-messages/alert-messages.md +0 -0
- package/src/core/components/ui/badge/badge.md +0 -0
- package/src/core/components/ui/badge/badge.ts +0 -0
- package/src/core/components/ui/button/button.md +0 -0
- package/src/core/components/ui/button/button.ts +0 -0
- package/src/core/components/ui/captcha/captcha.md +0 -0
- package/src/core/components/ui/card/card-footer.ts +0 -0
- package/src/core/components/ui/card/card-header-descripton.ts +0 -0
- package/src/core/components/ui/card/card-header.ts +0 -0
- package/src/core/components/ui/card/card-main.ts +0 -0
- package/src/core/components/ui/card/card.md +0 -0
- package/src/core/components/ui/card/card.ts +0 -0
- package/src/core/components/ui/divider/divider.ts +0 -0
- package/src/core/components/ui/form/css/form-control.ts +0 -0
- package/src/core/components/ui/form/fieldset/fieldset.ts +0 -0
- package/src/core/components/ui/form/fieldset/legend-description.ts +0 -0
- package/src/core/components/ui/form/fieldset/legend.ts +0 -0
- package/src/core/components/ui/form/form-layout/form-layout.md +0 -0
- package/src/core/components/ui/form/input/input.md +0 -0
- package/src/core/components/ui/form/input-autocomplete/input-autocomplete.ts +0 -0
- package/src/core/components/ui/form/radio/radio.md +0 -0
- package/src/core/components/ui/form/radio/radio.ts +0 -0
- package/src/core/components/ui/form/select/select.md +0 -0
- package/src/core/components/ui/form/switch/switch.md +0 -0
- package/src/core/components/ui/form/switch/switch.ts +0 -0
- package/src/core/components/ui/icon/icon.ts +0 -0
- package/src/core/components/ui/icon/icons.ts +1 -1
- package/src/core/components/ui/image/image.md +0 -0
- package/src/core/components/ui/image/image.ts +0 -0
- package/src/core/components/ui/loader/loader.md +0 -0
- package/src/core/components/ui/loader/loader.ts +0 -0
- package/src/core/components/ui/loader/styles/fixed.ts +0 -0
- package/src/core/components/ui/loader/styles/inline.ts +0 -0
- package/src/core/components/ui/menu/menu.ts +0 -0
- package/src/core/components/ui/modal/modal-actions.ts +0 -0
- package/src/core/components/ui/modal/modal-subtitle.ts +0 -0
- package/src/core/components/ui/modal/modal-title.ts +0 -0
- package/src/core/components/ui/modal/modal.md +0 -0
- package/src/core/components/ui/modal/modal.ts +0 -0
- package/src/core/components/ui/progress/progress.ts +0 -0
- package/src/core/components/ui/table/table-tbody.ts +0 -0
- package/src/core/components/ui/table/table-th.ts +0 -0
- package/src/core/components/ui/table/table.ts +0 -0
- package/src/core/components/ui/theme/theme-collection/core-variables.ts +0 -0
- package/src/core/components/ui/theme/theme-collection/dark.ts +0 -0
- package/src/core/components/ui/theme/theme-collection/light.ts +0 -0
- package/src/core/components/ui/theme/theme.ts +0 -0
- package/src/core/components/ui/toast/toast-item.ts +0 -0
- package/src/core/components/ui/toast/toast.ts +0 -0
- package/src/core/components/ui/tooltip/tooltip.ts +0 -0
- package/src/core/components/ui/ui.ts +0 -0
- package/src/core/directives/DataProvider.ts +0 -0
- package/src/core/directives/Wording.ts +0 -0
- package/src/core/mixins/Fetcher.ts +0 -0
- package/src/core/mixins/Subscriber.ts +0 -0
- package/src/core/mixins/TemplatesContainer.ts +0 -0
- package/src/core/utils/LocationHandler.ts +0 -0
- package/src/core/utils/Objects.ts +0 -0
- package/src/core/utils/Utils.ts +0 -0
- package/src/core/utils/aesCrypto.ts +0 -0
- package/src/core/utils/api.ts +0 -0
- package/src/core/utils/route.spec.ts +0 -0
- package/src/core/utils/route.ts +0 -0
- package/src/docs/code.ts +0 -0
- package/src/docs/docs.ts +0 -0
- package/src/docs/header/header.ts +0 -0
- package/src/docs/layout.ts +0 -0
- package/src/docs/navigation/navigation.ts +0 -0
- package/src/docs/search/docs-search.json +0 -0
- package/src/docs/search/markdown-renderer.ts +0 -0
- package/src/docs/search/page.ts +0 -0
- package/src/docs/search/search.ts +0 -0
- package/src/docs/tailwind/css/tailwind.css +0 -0
- package/src/docs/tailwind/css.d.ts +0 -0
- package/src/index.ts +0 -0
- package/src/test-utils/TestUtils.ts +0 -0
- package/src/tsconfig-model.json +0 -0
- package/src/tsconfig.json +0 -0
- package/src/tsconfig.tsbuildinfo +0 -0
- package/tailwind.config.js +0 -0
- package/templates-test.html +0 -0
- package/vite/config.js +0 -0
- package/vite.config.mts +0 -0
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# lit + tailwind + vite
|
|
2
|
+
|
|
3
|
+
**Some notes for an overview of Concorde's functioning**
|
|
4
|
+
|
|
5
|
+
## Standard Web components
|
|
6
|
+
A web component is simply a **custom HTML element** created using web standards:
|
|
7
|
+
|
|
8
|
+
**web component** = [Custom Elements](https://developer.mozilla.org/en-US/docs/Web/Web_Components/Using_custom_elements) + [shadowDom](https://developer.mozilla.org/fr/docs/Web/Web_Components/Using_shadow_DOM) + [HTML templates](https://developer.mozilla.org/fr/docs/Web/HTML/Element/template)
|
|
9
|
+
|
|
10
|
+
## Lit Library
|
|
11
|
+
|
|
12
|
+
Concorde components are written using the lightweight Lit library: https://lit.dev/.
|
|
13
|
+
|
|
14
|
+
A good portion of the elements documented on the Lit website are standard JavaScript concepts (e.g., [mixins](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Classes#mix-ins), [tagged template literals](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Template_literals#gabarits_%C3%A9tiquet%C3%A9s)).
|
|
15
|
+
|
|
16
|
+
The **library simplifies the writing of web components** by automating certain tasks:
|
|
17
|
+
|
|
18
|
+
- Creation of an **open mode shadow DOM** (the component is accessible from the outside via its shadow root property).
|
|
19
|
+
- [Rendering function](https://lit.dev/docs/components/rendering/) based on [tagged template literals](https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Template_literals#gabarits_%C3%A9tiquet%C3%A9s)
|
|
20
|
+
- [Reactive properties](https://lit.dev/docs/components/properties/) that trigger rendering when modified.
|
|
21
|
+
|
|
22
|
+
Our use of Lit rarely goes beyond this [hello world](https://lit.dev/playground/#sample=examples/hello-world)
|
|
23
|
+
|
|
24
|
+
## Typescript Language
|
|
25
|
+
|
|
26
|
+
We write the components in [TypeScript](https://www.typescriptlang.org/docs/handbook/typescript-in-5-minutes.html), which is then compiled into JS.
|
|
27
|
+
|
|
28
|
+
Static and inferred typing provides stronger validation of the program's functioning during compilation.
|
|
29
|
+
However, we often use the "any" type due to time constraints.
|
|
30
|
+
|
|
31
|
+
Lit uses TypeScript to simplify development through metadata:
|
|
32
|
+
- Simplified declaration of `custom elements` via @customElement
|
|
33
|
+
- Generation of `reactive properties` via @property.
|
|
34
|
+
|
|
35
|
+
☢️**Warning**:
|
|
36
|
+
- During development, we operate in interpreted mode, which is faster but allows errors that won't pass during the build.
|
|
37
|
+
- It is important to **build a distribution before pushing the code** to ensure everything is fine.
|
|
38
|
+
|
|
39
|
+
## Compatibility with Classic JS Libraries
|
|
40
|
+
|
|
41
|
+
Compatibility issues may arise when using JS libraries, particularly regarding DOM traversal.
|
|
42
|
+
This is because these libraries are blocked from traversing the DOM due to the presence of the shadow DOM.
|
|
43
|
+
Here are some examples of things that may cause problems:
|
|
44
|
+
|
|
45
|
+
- Latest FontAwesome in SVG mode, icons are not replaced
|
|
46
|
+
- Libraries associated with jQuery
|
|
47
|
+
- document.getElementById
|
|
48
|
+
- ...
|
|
49
|
+
|
|
50
|
+
## Topics to Explore for Further Learning
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
[🧱 Creating components](#docs/_getting-started/create-a-component.md/create-a-component)
|
|
54
|
+
|
|
55
|
+
[🎨 Adding styles](#docs/_getting-started/theming.md/theming)
|
|
56
|
+
|
|
57
|
+
[🥨 Sharing data](#docs/_getting-started/pubsub.md/pubsub)
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# The subscriber mixin
|
|
2
|
+
|
|
3
|
+
This is a mixin that is commonly extended by Concorde core components and destination components. Pure UI components usually don't extend it, especially those outside of form components.
|
|
4
|
+
|
|
5
|
+
## DataProvider Attribute: Automatic Filling of Subscriber Properties
|
|
6
|
+
|
|
7
|
+
Upon being added to the DOM (connectedCallback), subscribers search for the first occurrence of the `dataProvider` attribute in their parent's HTML structure.
|
|
8
|
+
|
|
9
|
+
The value of this attribute is used to obtain a publisher via the PublisherManager (see [🥨 Sharing Data](#docs/_getting-started/pubsub.md/pubsub)).
|
|
10
|
+
|
|
11
|
+
The subscriber then subscribes to the publisher as a data template to be filled.
|
|
12
|
+
|
|
13
|
+
The reactive properties of the component reflect in real-time the properties with the same name in the publisher.
|
|
14
|
+
|
|
15
|
+
This functionality is commonly used in the generic components [fetch](#core/components/functional/fetch/fetch.md/fetch), [queue](#core/components/functional/queue/queue.md/queue), and [list](#core/components/functional/list/list.md/list).
|
|
16
|
+
|
|
17
|
+
If the subscriber is inside another subscriber, it can subscribe to a data of its parent using the attribute `subDataProvider = 'address.of.my.data'` instead of the parent's data. This allows for dynamic behavior.
|
|
18
|
+
|
|
19
|
+
## Automated Translation
|
|
20
|
+
|
|
21
|
+
In a similar manner, searching for ancestor attributes can be used to configure automatic translation for any property starting with "wording" and ending with a label identifier recognized by the wordingProvider API.
|
|
22
|
+
|
|
23
|
+
Normally, this API is globally configured and not within the component. Therefore, remember to prefix translatable label identifiers present in the ticketing system, for example, with "wording".
|
|
24
|
+
|
|
25
|
+
## Reactive Property `props`
|
|
26
|
+
|
|
27
|
+
The value of this property can be provided as a JSON object or any other value. This value is then assigned to the associated publisher via the `dataProvider` attribute. As a result, the reactive properties of all subscribers associated with the same `dataProvider` are filled as mentioned above.
|
|
28
|
+
|
|
29
|
+
## Disabling Automatic Filling of Reactive Properties
|
|
30
|
+
|
|
31
|
+
It is possible to disable the automatic filling of reactive properties in a particular component. To do so, set the variable `noAutoFill = true` in the component's class. However, the reactive property `props` will still be updated.
|
|
32
|
+
|
|
33
|
+
For example, `sonic-subscriber` and `sonic-fetch` have this attribute because they do not have reactive properties.
|
|
34
|
+
|
|
35
|
+
**☢ CAUTION:** When creating an object of type Subscriber or Fetcher, make sure to use the mixins and not directly extend the concrete fetch component (`sonic-fetch`) and subscriber component (`sonic-subscriber`). This is because the `noAutofill = true` attribute is set in those components.
|
|
36
|
+
|
|
37
|
+
**TIPS:**
|
|
38
|
+
If you disable automatic filling, you will likely make the rendering dynamic by writing expressions like `this.props.my.subproperty`. If `props` is updated, the rendering will be triggered. However, if `this.props.my.subproperty` is directly modified, the rendering will not be triggered. To achieve more reactivity, you can enable rendering when any subproperty is modified. Simply set the variable `renderOnPropsInternalChange = true` in the class that implements the corresponding mixin.
|
|
39
|
+
|
|
40
|
+
## Data Binding
|
|
41
|
+
|
|
42
|
+
Suppose that:
|
|
43
|
+
|
|
44
|
+
- You have a subscriber subscribed to a publisher via its `dataProvider` attribute.
|
|
45
|
+
- The published data has the following structure:
|
|
46
|
+
|
|
47
|
+
<sonic-code language="javascript">
|
|
48
|
+
<template>
|
|
49
|
+
{"img": { "avatar": "my-avatar.jpg", "caption": "look at my smile" }, "email": "an.email@example.com" }
|
|
50
|
+
</template>
|
|
51
|
+
</sonic-code>
|
|
52
|
+
- We want to keep the display of an image and its `title` attribute up to date, as well as a "contact" button to email the person in the photo. The content of the subscriber could be as follows:
|
|
53
|
+
|
|
54
|
+
<sonic-code language="html">
|
|
55
|
+
<template>
|
|
56
|
+
<img data-bind ::src="$img.avatar" ::title="ucFirst|$img.caption" />
|
|
57
|
+
<a data-bind ::href="mailto:$email" ::inner-html="$email"></a>
|
|
58
|
+
</template>
|
|
59
|
+
</sonic-code>
|
|
60
|
+
|
|
61
|
+
This example also illustrates:
|
|
62
|
+
|
|
63
|
+
- Binding to subproperties using dot syntax, as done for the `src` attribute of the `img` tag.
|
|
64
|
+
- Using a simple expression to include the property within a string, as in creating a `mailto` link.
|
|
65
|
+
- Using formatting functions, as in the `title` attribute of the `img` tag. You can find (and add) formatting functions in the `core/utils/Format.ts` file.
|
|
66
|
+
- Writing for properties that are in camel case. Convert everything to lowercase and add hyphens. Note that `innerHTML` (or `outerHTML`) is a special case where no hyphens are added between each letter.
|
|
67
|
+
|
|
68
|
+
**Note:** Data binding implies that updating the `img.src` data via the publisher will change the photo without any additional calls.
|
|
69
|
+
|
|
70
|
+
**Special Variables:**
|
|
71
|
+
- `_self_` targets the root of the data. This is useful, for example, when the data is a pure string.
|
|
72
|
+
- `_parent_` targets the parent publisher of the current publisher, if any. For example, the subscribers of lists have the complete data of the list as their parent.
|
|
73
|
+
- `_metadata_` is only used in the case of *sonic-list* at the moment. In a simple list, `_metadata_` see the (list)[] component for further details
|
|
74
|
+
|
|
75
|
+
**Disabling this functionality:**
|
|
76
|
+
You can disable data binding if it is not needed by calling `DataBinding.disable()`.
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Installation
|
|
2
|
+
|
|
3
|
+
## Starter
|
|
4
|
+
|
|
5
|
+
The easiest way to use Concorde is by using the Concorde starter.
|
|
6
|
+
The following command creates a new Vite project in TypeScript mode with Tailwind and an example component to get started.
|
|
7
|
+
|
|
8
|
+
<sonic-code language="shell">
|
|
9
|
+
<template>
|
|
10
|
+
npx @supersoniks/create-concorde-ts-starter "project_name"
|
|
11
|
+
</template>
|
|
12
|
+
</sonic-code>
|
|
13
|
+
|
|
14
|
+
## Brand New Vite Project
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
For a more manual configuration, you can refer to the following sections. <br/>
|
|
18
|
+
However, the Tailwind configuration is not mentioned at the moment.
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
### Creating the Project
|
|
22
|
+
|
|
23
|
+
<sonic-code language="shell">
|
|
24
|
+
<template>
|
|
25
|
+
# Pure JavaScript project
|
|
26
|
+
yarn create vite --template vanilla-js
|
|
27
|
+
# TypeScript project
|
|
28
|
+
# (it is recommended to use this approach, which installs Lit separately if needed, via "yarn add lit")
|
|
29
|
+
yarn create vite --template vanilla-ts
|
|
30
|
+
# TypeScript + Lit project
|
|
31
|
+
# (creating new web components, for example, to extend the fetch or subscriber mixins)
|
|
32
|
+
yarn create vite --template lit-ts
|
|
33
|
+
</template>
|
|
34
|
+
</sonic-code>
|
|
35
|
+
|
|
36
|
+
Using Lit with TypeScript requires the following configuration in the "compilerOptions" section of the `tsconfig.json` file:
|
|
37
|
+
|
|
38
|
+
<sonic-code language="json">
|
|
39
|
+
<template>
|
|
40
|
+
"experimentalDecorators": true,
|
|
41
|
+
"useDefineForClassFields": false
|
|
42
|
+
</template>
|
|
43
|
+
</sonic-code>
|
|
44
|
+
|
|
45
|
+
### Installing Concorde
|
|
46
|
+
|
|
47
|
+
Navigate to the project folder created and perform the installation:
|
|
48
|
+
|
|
49
|
+
<sonic-code language="shell">
|
|
50
|
+
<template>
|
|
51
|
+
yarn add @supersoniks/concorde
|
|
52
|
+
</template>
|
|
53
|
+
</sonic-code>
|
|
54
|
+
|
|
55
|
+
### Development / Build
|
|
56
|
+
|
|
57
|
+
<sonic-code language="shell">
|
|
58
|
+
<template>
|
|
59
|
+
# Development (you can add `--host` after the command chain in package.json's dev script instead of typing it each time as shown below)
|
|
60
|
+
yarn dev --host
|
|
61
|
+
# Build
|
|
62
|
+
yarn build
|
|
63
|
+
</template>
|
|
64
|
+
</sonic-code>
|
|
65
|
+
|
|
66
|
+
## Shortcut Imports
|
|
67
|
+
|
|
68
|
+
Shortcut imports work by default in JavaScript, but in TypeScript, they are activated by choice as they inject data into *tsconfig.json*. Here is the command:
|
|
69
|
+
|
|
70
|
+
<sonic-code language="shell">
|
|
71
|
+
<template>
|
|
72
|
+
npx concorde enable-short-paths
|
|
73
|
+
</template>
|
|
74
|
+
</sonic-code>
|
|
75
|
+
|
|
76
|
+
Shortcut imports replace the actual paths with aliases as follows:
|
|
77
|
+
|
|
78
|
+
* `@supersoniks/concorde/core/components/functional_or_ui/component/component` becomes `@supersoniks/concorde/functional_or_ui/component`
|
|
79
|
+
* `@supersoniks/concorde/core/mixins_or_utils/class_name` becomes `@supersoniks/concorde/mixins_or_utils/class_name`
|
|
80
|
+
|
|
81
|
+
The original paths remain accessible. Shortcut imports are used for the examples later in this documentation.
|
|
82
|
+
|
|
83
|
+
## Usage
|
|
84
|
+
|
|
85
|
+
### Simple Integration in HTML
|
|
86
|
+
|
|
87
|
+
Import needed component in `main.ts` or wherever you want to use it:
|
|
88
|
+
|
|
89
|
+
<sonic-code language="typescript">
|
|
90
|
+
<template>
|
|
91
|
+
import "@supersoniks/concorde/ui/button";
|
|
92
|
+
</template>
|
|
93
|
+
</sonic-code>
|
|
94
|
+
|
|
95
|
+
Then in the render function ofyour component or in the HTML of the web page that includes the compiled JS, use the component as follows:
|
|
96
|
+
|
|
97
|
+
<sonic-code>
|
|
98
|
+
<template>
|
|
99
|
+
<sonic-button variant="outline">My button</sonic-button>
|
|
100
|
+
</template>
|
|
101
|
+
</sonic-code>
|
|
102
|
+
|
|
103
|
+
### Using a Mixin to Create a New Lit Component
|
|
104
|
+
|
|
105
|
+
For example, create a file `my-element.ts` at the root:
|
|
106
|
+
|
|
107
|
+
<sonic-code language="typescript">
|
|
108
|
+
<template>
|
|
109
|
+
import { html, LitElement } from "lit";
|
|
110
|
+
import { customElement, property } from "lit/decorators.js";
|
|
111
|
+
import Fetcher from "@supersoniks/concorde/mixins/Fetcher";
|
|
112
|
+
import Subscriber from "@supersoniks/concorde/mixins/Subscriber";
|
|
113
|
+
|
|
114
|
+
@customElement("my-element")
|
|
115
|
+
export class SonicComponent extends Fetcher(Subscriber(LitElement)) {
|
|
116
|
+
@property() email = "";
|
|
117
|
+
@property() first_name = "";
|
|
118
|
+
@property() last_name = "";
|
|
119
|
+
|
|
120
|
+
render() {
|
|
121
|
+
return html`<div>
|
|
122
|
+
${this.first_name} ${this.last_name} : ${this.email}
|
|
123
|
+
</div>`;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
</template>
|
|
127
|
+
</sonic-code>
|
|
128
|
+
|
|
129
|
+
Import component `main.ts` or `main.js` or any other component that uses it to be compiled
|
|
130
|
+
|
|
131
|
+
<sonic-code language="typescript">
|
|
132
|
+
<template>
|
|
133
|
+
import "./my-element";
|
|
134
|
+
</template>
|
|
135
|
+
</sonic-code>
|
|
136
|
+
|
|
137
|
+
In the HTML of a JS or TS component or in the HTML of the web page containing the compiled JS:
|
|
138
|
+
|
|
139
|
+
<sonic-code language="html">
|
|
140
|
+
<template>
|
|
141
|
+
<my-element serviceURL="https://reqres.in" dataProvider="api/users/2" key="data"></my-element>
|
|
142
|
+
</template>
|
|
143
|
+
</sonic-code>
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
# Creating components
|
|
2
|
+
|
|
3
|
+
## Where to put it?
|
|
4
|
+
|
|
5
|
+
In this document, we consider the src directory of the project as the root.<br>
|
|
6
|
+
We describe how we organize our components as an example, however it depends on your project.
|
|
7
|
+
|
|
8
|
+
In concorde each component is currently organized in the following directory structure (at least we try):
|
|
9
|
+
|
|
10
|
+
- **/core/components/functional/component-name/component-name.ts**
|
|
11
|
+
Generic/functional/generally unstyled component.
|
|
12
|
+
The component usually doesn't use any other concrete components.
|
|
13
|
+
- **/core/components/ui/component-name/component-name.ts**
|
|
14
|
+
Generic but UI-oriented component.
|
|
15
|
+
The component usually only uses generic components and other UI components.
|
|
16
|
+
- **la-billetterie/components/atoms/component-name/component-name.ts**
|
|
17
|
+
The component is intended to have a concrete usage within our ticketing system **"la-billetterie"**.
|
|
18
|
+
It usually only uses generic components from `core` and possibly other atoms.
|
|
19
|
+
- **la-billetterie/components/concrete-destination/component-name/component-name.ts**
|
|
20
|
+
The component has a specific destination: (event / cart / gift card): `/components/destination/`
|
|
21
|
+
The component uses various components, usually from the `/components/atoms` directory.
|
|
22
|
+
It does not use components at the same level in the file hierarchy.
|
|
23
|
+
|
|
24
|
+
## Starting from a Simple Model
|
|
25
|
+
|
|
26
|
+
You can copy `example.ts` from the source to the desired destination to start with.
|
|
27
|
+
This file contains a web component in the form of a class that extends the `Subscriber` mixin, with a reactive property and a render function.
|
|
28
|
+
|
|
29
|
+
<sonic-code language="javascript">
|
|
30
|
+
<template>
|
|
31
|
+
import { html, LitElement } from "lit";
|
|
32
|
+
import { customElement, property } from "lit/decorators.js";
|
|
33
|
+
import Subscriber from "@supersoniks/concorde/core/mixins/Subscriber";
|
|
34
|
+
|
|
35
|
+
@customElement("sonic-example")
|
|
36
|
+
export class SonicComponent extends Subscriber(LitElement) {
|
|
37
|
+
@property() text = "Example";
|
|
38
|
+
render() {
|
|
39
|
+
return html`${this.text}`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
</template>
|
|
43
|
+
</sonic-code>
|
|
44
|
+
|
|
45
|
+
**You can remove the dependency on `Subscriber`** if automatic population of the component with external data is not required.
|
|
46
|
+
For example, for a UI component:
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
<sonic-code language="javascript">
|
|
50
|
+
<template>
|
|
51
|
+
import { html, LitElement } from "lit";
|
|
52
|
+
import { customElement, property } from "lit/decorators.js";
|
|
53
|
+
|
|
54
|
+
@customElement("sonic-example")
|
|
55
|
+
export class SonicComponent extends LitElement {
|
|
56
|
+
@property() text = "Example";
|
|
57
|
+
render() {
|
|
58
|
+
return html`${this.text}`;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
</template>
|
|
62
|
+
</sonic-code>
|
|
63
|
+
|
|
64
|
+
Regarding `Subscriber`, see:
|
|
65
|
+
|
|
66
|
+
- [🔔 Subscriber](#docs/_core-concept/subscriber.md/subscriber)
|
|
67
|
+
- [🥨 Sharing Data](#docs/_getting-started/pubsub.md/pubsub)
|
|
68
|
+
|
|
69
|
+
### Naming the Component
|
|
70
|
+
|
|
71
|
+
The class name is not necessarily important. However, it is important to **give it a component name prefixed with "sonic"** (or a prefix of your own) using the dedicated metadata already present in the copied document. For example, a button component would be named as follows:
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
<sonic-code language="typescript">
|
|
75
|
+
<template>
|
|
76
|
+
@customElement("sonic-button")
|
|
77
|
+
</template>
|
|
78
|
+
</sonic-code>
|
|
79
|
+
|
|
80
|
+
For less generic components with a specific destination, we advise to include the destination in the name.
|
|
81
|
+
For example, for a "title" component in the "event" destination, the name would be simply:
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
<sonic-code language="typescript">
|
|
85
|
+
<template>
|
|
86
|
+
@customElement("sonic-event-title")
|
|
87
|
+
</template>
|
|
88
|
+
</sonic-code>
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
## Modifying It
|
|
92
|
+
|
|
93
|
+
#### Creating Reactive Properties and Modifying the Render Function
|
|
94
|
+
|
|
95
|
+
To do this, study the functioning of https://lit.dev and also refer to [Subscriber](#docs/_core-concept/subscriber.md/subscriber).
|
|
96
|
+
|
|
97
|
+
#### HTML Structure of a Component
|
|
98
|
+
|
|
99
|
+
The HTML structure of a component should remain as simple as possible.
|
|
100
|
+
|
|
101
|
+
Ideally, there should be only one additional level of elements in addition to slots.
|
|
102
|
+
|
|
103
|
+
- **The main component is already a wrapper**.
|
|
104
|
+
It receives classes to manage its layout, but it should not style internal elements.
|
|
105
|
+
- **Slots handle the visual organization** of elements.
|
|
106
|
+
- **The specificity of the component is expressed in this additional level** by adding a list, a functional native element (e.g., button), or another component.
|
|
107
|
+
|
|
108
|
+
This leads to the creation of more components and thus raises questions about the hierarchical organization of files. However, this tends to atomize their roles.
|
|
109
|
+
|
|
110
|
+
## Referencing It
|
|
111
|
+
|
|
112
|
+
To compile the component, it needs to be referenced somewhere through an import statement. In particular, it is important to reference it in any component that uses it.
|
|
113
|
+
|
|
114
|
+
In the case where it can be directly used in a page, it should also be globally referenced, especially considering the creation of **specific bundles** in the future.
|
|
115
|
+
|
|
116
|
+
Here's where we add imports based on the component's location inside concorde as an example
|
|
117
|
+
|
|
118
|
+
- **/core/components/functional/component-name/component-name.ts**
|
|
119
|
+
In `/core/components/functional/functional.ts`, which is referenced in core.ts and imported in `index.ts`.
|
|
120
|
+
- **/core/components/ui/component-name/component-name.ts**
|
|
121
|
+
In `/core/components/ui/ui.ts`, which is referenced in core.ts and imported in `index.ts`.
|
|
122
|
+
- **la-billetterie/components/atoms/component-name/component-name.ts**
|
|
123
|
+
Nowhere else but where it will be used, except for possible **temporary** tests, for example, in `index.ts`.
|
|
124
|
+
- **la-billetterie/components/concrete-destination/component-name/component-name.ts**
|
|
125
|
+
In `la-billetterie/components/concrete-destination/destination-concrete.ts`.
|
|
126
|
+
If it's a new destination, you'll need to create the corresponding import .ts file and import it in `la-billetterie.ts`.
|
|
127
|
+
|
|
128
|
+
## Using It
|
|
129
|
+
|
|
130
|
+
As a reminder, the component is simply integrated into the context by adding a tag with the component's name, for example:
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
<sonic-code language="html">
|
|
134
|
+
<template>
|
|
135
|
+
<sonic-event-title></sonic-event-title>
|
|
136
|
+
</template>
|
|
137
|
+
</sonic-code>
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# My first subscriber component
|
|
2
|
+
|
|
3
|
+
Learn how to build a subscriber component, styled with tailwind,
|
|
4
|
+
which could be used as a regular component or could be filled from a dataprovider.
|
|
5
|
+
|
|
6
|
+
## Create a classic lit component
|
|
7
|
+
|
|
8
|
+
<sonic-code language="javascript" >
|
|
9
|
+
<template>
|
|
10
|
+
import { html, LitElement, nothing } from "lit";
|
|
11
|
+
import { customElement, property } from "lit/decorators.js";
|
|
12
|
+
// name component
|
|
13
|
+
@customElement("docs-user")
|
|
14
|
+
export class user extends LitElement {
|
|
15
|
+
// set a few props
|
|
16
|
+
@property({ type: String }) first_name = "";
|
|
17
|
+
@property({ type: String }) last_name = "";
|
|
18
|
+
@property({ type: String }) avatar = "";
|
|
19
|
+
@property({ type: String }) email = "";
|
|
20
|
+
// output
|
|
21
|
+
render() {
|
|
22
|
+
return html`
|
|
23
|
+
<img src="${this.avatar}" /> <br>
|
|
24
|
+
${this.first_name} ${this.last_name} <br>
|
|
25
|
+
${this.email}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
</template>
|
|
29
|
+
</sonic-code>
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
### Style with tailwind and ui components
|
|
33
|
+
|
|
34
|
+
First export tailwind, in a tailwind.ts file, stylesheet to add it in our component when needed.
|
|
35
|
+
|
|
36
|
+
<sonic-code language="javascript">
|
|
37
|
+
<template>
|
|
38
|
+
import { css, unsafeCSS } from "lit";
|
|
39
|
+
import tailwindImport from "./css/tailwind.css?inline";
|
|
40
|
+
export const tailwind = css`${unsafeCSS(tailwindImport)}`;
|
|
41
|
+
</template>
|
|
42
|
+
</sonic-code>
|
|
43
|
+
|
|
44
|
+
<sonic-code language="javascript">
|
|
45
|
+
<template>
|
|
46
|
+
import { html, LitElement, nothing } from "lit";
|
|
47
|
+
import { customElement, property } from "lit/decorators.js";
|
|
48
|
+
// add tailwind and needed components
|
|
49
|
+
import { tailwind } from "../tailwind";
|
|
50
|
+
import '@supersoniks/concode/ui/image'
|
|
51
|
+
import '@supersoniks/concode/ui/button'
|
|
52
|
+
import '@supersoniks/concode/ui/icon'
|
|
53
|
+
//
|
|
54
|
+
@customElement("docs-user")
|
|
55
|
+
export class user extends LitElement {
|
|
56
|
+
// add tailwind stylesheed
|
|
57
|
+
static styles = [tailwind];
|
|
58
|
+
@property({ type: String }) first_name = "";
|
|
59
|
+
@property({ type: String }) last_name = "";
|
|
60
|
+
@property({ type: String }) avatar = "";
|
|
61
|
+
@property({ type: String }) email = "";
|
|
62
|
+
// use utility class in your markup
|
|
63
|
+
render() {
|
|
64
|
+
return html`<div
|
|
65
|
+
class="flex items-center gap-3 rounded-md hover:bg-neutral-50 -mx-2 p-2"
|
|
66
|
+
>
|
|
67
|
+
<sonic-image
|
|
68
|
+
src=${this.avatar}
|
|
69
|
+
rounded="md"
|
|
70
|
+
ratio="1/1"
|
|
71
|
+
class="w-16 block"
|
|
72
|
+
></sonic-image>
|
|
73
|
+
<div>
|
|
74
|
+
<div>
|
|
75
|
+
${this.first_name} <span class="font-bold">${this.last_name}</span>
|
|
76
|
+
</div>
|
|
77
|
+
<div class="text-sm text-neutral-400">${this.email}</div>
|
|
78
|
+
</div>
|
|
79
|
+
<div class="ml-auto relative">
|
|
80
|
+
<sonic-button
|
|
81
|
+
href="mailto:${this.email}"
|
|
82
|
+
size="sm"
|
|
83
|
+
variant="outline"
|
|
84
|
+
shape="circle"
|
|
85
|
+
class="relative"
|
|
86
|
+
icon
|
|
87
|
+
>
|
|
88
|
+
<sonic-icon library="iconoir" name="chat-bubble"></sonic-icon>
|
|
89
|
+
</sonic-button>
|
|
90
|
+
</div>
|
|
91
|
+
</div>`;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
</template>
|
|
95
|
+
</sonic-code>
|
|
96
|
+
|
|
97
|
+
### Basic usage
|
|
98
|
+
|
|
99
|
+
Reactive properties can be filled by its attributes as a simple lit component.
|
|
100
|
+
|
|
101
|
+
<sonic-code>
|
|
102
|
+
<template>
|
|
103
|
+
<docs-user
|
|
104
|
+
first_name="Paul"
|
|
105
|
+
last_name="Metrand"
|
|
106
|
+
avatar="/img/paul_metrand_xs.jpg"
|
|
107
|
+
email="paulmetrand@concorde.fr"
|
|
108
|
+
></docs-user>
|
|
109
|
+
</template>
|
|
110
|
+
</sonic-code>
|
|
111
|
+
|
|
112
|
+
## Add Subscriber mixin
|
|
113
|
+
|
|
114
|
+
Import Subscriber mixin, and add it around LitElement.
|
|
115
|
+
<sonic-code language="javascript">
|
|
116
|
+
<template>
|
|
117
|
+
import { html, LitElement, nothing } from "lit";
|
|
118
|
+
import { customElement, property } from "lit/decorators.js";
|
|
119
|
+
import { tailwind } from "../tailwind";
|
|
120
|
+
import Subscriber from "@supersoniks/concorde/core/mixins/Subscriber";
|
|
121
|
+
@customElement("docs-user")
|
|
122
|
+
export class user extends Subscriber(LitElement) {
|
|
123
|
+
//...
|
|
124
|
+
}
|
|
125
|
+
</template>
|
|
126
|
+
</sonic-code>
|
|
127
|
+
|
|
128
|
+
## Autofill properties from a dataProvider
|
|
129
|
+
|
|
130
|
+
Without a dataProvider attribute, a subscriber set its own dataprovider from first ancestor found, and then reactive properties automatically filled and update from it.
|
|
131
|
+
A fetcher is a simple component which set its fetch result to props of its dataprovider.
|
|
132
|
+
<sonic-code >
|
|
133
|
+
<template>
|
|
134
|
+
<sonic-fetch
|
|
135
|
+
serviceURL="https://reqres.in"
|
|
136
|
+
dataProvider="api/users/3"
|
|
137
|
+
key="data">
|
|
138
|
+
<docs-user></docs-user>
|
|
139
|
+
</sonic-fetch>
|
|
140
|
+
</template>
|
|
141
|
+
</sonic-code>
|
|
142
|
+
|
|
143
|
+
A subscriber can subscribe data from anywhere in the DOM, with its dataprovider set as a provider id.
|
|
144
|
+
<sonic-code >
|
|
145
|
+
<template>
|
|
146
|
+
<sonic-fetch
|
|
147
|
+
serviceURL="https://reqres.in"
|
|
148
|
+
dataProvider="api/users/2"
|
|
149
|
+
key="data"></sonic-fetch>
|
|
150
|
+
<docs-user dataProvider="api/users/2" ></docs-user>
|
|
151
|
+
<docs-user dataProvider="api/users/2" ></docs-user>
|
|
152
|
+
<docs-user dataProvider="api/users/2" ></docs-user>
|
|
153
|
+
</template>
|
|
154
|
+
</sonic-code>
|
|
155
|
+
|
|
156
|
+
|
|
157
|
+
<sonic-code >
|
|
158
|
+
<template>
|
|
159
|
+
|
|
160
|
+
<div class="grid grid-cols-1 gap-4">
|
|
161
|
+
<form formDataProvider="userPreview" class="grid grid-cols-4 gap-3" >
|
|
162
|
+
<sonic-input label="First name" type="text" name="first_name" placeholder="John" value="Paul"></sonic-input>
|
|
163
|
+
<sonic-input label="Last name" type="text" name="last_name" placeholder="Doe" value="Metrand"></sonic-input>
|
|
164
|
+
<sonic-input class="col-span-2" label="email" type="text" name="email" placeholder="johndoe@concorde.fr" value="paulmetrand@concorde.fr"></sonic-input>
|
|
165
|
+
<sonic-input type="file" name="avatar" value="/img/paul_metrand_xs.jpg"></sonic-input>
|
|
166
|
+
</form>
|
|
167
|
+
<sonic-divider align="left">Preview before submit</sonic-divider>
|
|
168
|
+
<docs-user dataProvider="userPreview" ></docs-user>
|
|
169
|
+
<sonic-button onClick="alert(JSON.stringify(SonicPublisherManager.get('userPreview').get()))">
|
|
170
|
+
Update data
|
|
171
|
+
</sonic-button>
|
|
172
|
+
</div>
|
|
173
|
+
</template>
|
|
174
|
+
</sonic-code>
|