@supersoniks/concorde 3.1.0 → 3.1.2

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 (97) hide show
  1. package/build-infos.json +1 -1
  2. package/concorde-core.bundle.js +227 -142
  3. package/concorde-core.es.js +831 -726
  4. package/dist/concorde-core.bundle.js +227 -142
  5. package/dist/concorde-core.es.js +831 -726
  6. package/dist/img/paul_metrand.jpg +0 -0
  7. package/dist/img/paul_metrand_xs.jpg +0 -0
  8. package/package.json +1 -1
  9. package/public/img/paul_metrand.jpg +0 -0
  10. package/public/img/paul_metrand_xs.jpg +0 -0
  11. package/src/core/_types/types.ts +1 -0
  12. package/src/core/components/functional/list/list.md +8 -3
  13. package/src/core/components/functional/submit/submit.ts +3 -2
  14. package/src/core/components/ui/_css/scroll.ts +3 -2
  15. package/src/core/components/ui/_css/size.ts +5 -1
  16. package/src/core/components/ui/form/checkbox/checkbox.ts +31 -21
  17. package/src/core/components/ui/form/input/input.ts +70 -36
  18. package/src/core/components/ui/form/input-autocomplete/input-autocomplete.ts +101 -35
  19. package/src/core/components/ui/form/select/select.ts +1 -0
  20. package/src/core/components/ui/form/textarea/textarea.md +2 -3
  21. package/src/core/components/ui/form/textarea/textarea.ts +51 -24
  22. package/src/core/components/ui/progress/progress.md +4 -6
  23. package/src/core/components/ui/progress/progress.ts +28 -13
  24. package/src/core/components/ui/table/table.md +15 -27
  25. package/src/core/components/ui/table/table.ts +26 -15
  26. package/src/core/components/ui/theme/theme-collection/core-variables.ts +20 -12
  27. package/src/core/components/ui/tooltip/tooltip.md +45 -0
  28. package/src/core/components/ui/tooltip/tooltip.ts +63 -18
  29. package/src/core/mixins/FormElement.ts +50 -24
  30. package/src/core/utils/PublisherProxy.ts +3 -2
  31. package/src/docs/_getting-started/my-first-subscriber.md +174 -0
  32. package/src/docs/_getting-started/start.md +2 -2
  33. package/src/docs/example/users.ts +43 -48
  34. package/src/docs/header/header.ts +217 -217
  35. package/src/docs/navigation/navigation.ts +2 -2
  36. package/src/docs/search/docs-search.json +139 -4
  37. package/src/docs/search/search.ts +6 -4
  38. package/docs/assets/index--bDsd7qW.css +0 -1
  39. package/docs/assets/index-Ce3mr_lI.js +0 -4040
  40. package/docs/css/docs.css +0 -0
  41. package/docs/img/concorde-logo.svg +0 -1
  42. package/docs/img/concorde.png +0 -0
  43. package/docs/img/concorde_def.png +0 -0
  44. package/docs/index.html +0 -132
  45. package/docs/src/core/components/functional/date/date.md +0 -290
  46. package/docs/src/core/components/functional/fetch/fetch.md +0 -117
  47. package/docs/src/core/components/functional/if/if.md +0 -16
  48. package/docs/src/core/components/functional/list/list.md +0 -194
  49. package/docs/src/core/components/functional/mix/mix.md +0 -41
  50. package/docs/src/core/components/functional/queue/queue.md +0 -87
  51. package/docs/src/core/components/functional/router/router.md +0 -112
  52. package/docs/src/core/components/functional/sdui/default-library.json +0 -108
  53. package/docs/src/core/components/functional/sdui/example.json +0 -99
  54. package/docs/src/core/components/functional/sdui/sdui.md +0 -356
  55. package/docs/src/core/components/functional/states/states.md +0 -87
  56. package/docs/src/core/components/functional/submit/submit.md +0 -48
  57. package/docs/src/core/components/functional/subscriber/subscriber.md +0 -91
  58. package/docs/src/core/components/functional/value/value.md +0 -35
  59. package/docs/src/core/components/ui/alert/alert.md +0 -121
  60. package/docs/src/core/components/ui/badge/badge.md +0 -102
  61. package/docs/src/core/components/ui/button/button.md +0 -184
  62. package/docs/src/core/components/ui/captcha/captcha.md +0 -12
  63. package/docs/src/core/components/ui/card/card.md +0 -96
  64. package/docs/src/core/components/ui/divider/divider.md +0 -35
  65. package/docs/src/core/components/ui/form/checkbox/checkbox.md +0 -96
  66. package/docs/src/core/components/ui/form/fieldset/fieldset.md +0 -129
  67. package/docs/src/core/components/ui/form/form-actions/form-actions.md +0 -77
  68. package/docs/src/core/components/ui/form/form-layout/form-layout.md +0 -43
  69. package/docs/src/core/components/ui/form/input/input.md +0 -168
  70. package/docs/src/core/components/ui/form/input-autocomplete/input-autocomplete.md +0 -130
  71. package/docs/src/core/components/ui/form/radio/radio.md +0 -86
  72. package/docs/src/core/components/ui/form/select/select.md +0 -99
  73. package/docs/src/core/components/ui/form/textarea/textarea.md +0 -66
  74. package/docs/src/core/components/ui/group/group.md +0 -75
  75. package/docs/src/core/components/ui/icon/icon.md +0 -125
  76. package/docs/src/core/components/ui/icon/icons.json +0 -1
  77. package/docs/src/core/components/ui/image/image.md +0 -107
  78. package/docs/src/core/components/ui/link/link.md +0 -43
  79. package/docs/src/core/components/ui/loader/loader.md +0 -37
  80. package/docs/src/core/components/ui/menu/menu.md +0 -288
  81. package/docs/src/core/components/ui/modal/modal.md +0 -123
  82. package/docs/src/core/components/ui/pop/pop.md +0 -79
  83. package/docs/src/core/components/ui/progress/progress.md +0 -65
  84. package/docs/src/core/components/ui/table/table.md +0 -467
  85. package/docs/src/core/components/ui/tooltip/tooltip.md +0 -37
  86. package/docs/src/docs/_core-concept/overview.md +0 -57
  87. package/docs/src/docs/_core-concept/subscriber.md +0 -76
  88. package/docs/src/docs/_getting-started/concorde-outside.md +0 -141
  89. package/docs/src/docs/_getting-started/create-a-component.md +0 -137
  90. package/docs/src/docs/_getting-started/pubsub.md +0 -150
  91. package/docs/src/docs/_getting-started/start.md +0 -37
  92. package/docs/src/docs/_getting-started/theming.md +0 -91
  93. package/docs/src/docs/search/docs-search.json +0 -3737
  94. package/docs/src/tag-list.json +0 -1
  95. package/docs/src/tsconfig.json +0 -113
  96. package/docs/svg/regular/plane.svg +0 -1
  97. package/docs/svg/solid/plane.svg +0 -1
@@ -1,9 +1,13 @@
1
- import {PublisherManager} from "@supersoniks/concorde/core/utils/PublisherProxy";
2
- import {property} from "lit/decorators.js";
3
- import {SubscriberInterface} from "@supersoniks/concorde/core/mixins/Subscriber";
1
+ import { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
2
+ import { property } from "lit/decorators.js";
3
+ import { SubscriberInterface } from "@supersoniks/concorde/core/mixins/Subscriber";
4
4
  import Objects from "@supersoniks/concorde/core/utils/Objects";
5
- import {PublisherInterface, HTMLFormControl, CoreJSType} from "../_types/types";
6
- import {MixinArgsType} from "../_types/types";
5
+ import {
6
+ PublisherInterface,
7
+ HTMLFormControl,
8
+ CoreJSType,
9
+ } from "../_types/types";
10
+ import { MixinArgsType } from "../_types/types";
7
11
  type Constructor<T> = new (...args: MixinArgsType[]) => T;
8
12
  type FormElementValue = string | string[] | object | null | undefined;
9
13
  export interface FormElementInterface extends SubscriberInterface {
@@ -42,16 +46,17 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
42
46
  *
43
47
  */
44
48
  class FormElement extends superClass implements FormElementInterface {
45
- @property({type: Boolean, reflect: true}) touched = false;
46
- @property({type: Boolean}) error = false;
47
- @property({type: Boolean}) autofocus = false;
48
- @property({type: Boolean}) required = false;
49
- @property({type: Boolean}) forceAutoFill = false;
50
- @property({type: Boolean}) disabled: true | null = null;
49
+ @property({ type: Boolean, reflect: true }) touched = false;
50
+ @property({ type: Boolean }) error = false;
51
+ @property({ type: Boolean }) autofocus = false;
52
+ @property({ type: Boolean }) required = false;
53
+ @property({ type: Boolean }) forceAutoFill = false;
54
+ @property({ type: Boolean }) disabled: true | null = null;
51
55
 
52
56
  /* Attribut data-aria-label pour passer aria-label */
53
- @property({type: String, attribute: "data-aria-label"}) ariaLabel?: string;
54
- @property({type: String, attribute: "data-aria-labelledby"})
57
+ @property({ type: String, attribute: "data-aria-label" })
58
+ ariaLabel?: string;
59
+ @property({ type: String, attribute: "data-aria-labelledby" })
55
60
  ariaLabelledby?: string;
56
61
 
57
62
  onValueAssign?: (v: string) => void;
@@ -84,7 +89,8 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
84
89
  return this._name;
85
90
  }
86
91
  set name(value: string) {
87
- if (this.hasAttribute("name") && !this.forceAutoFill) value = this.getAttribute("name");
92
+ if (this.hasAttribute("name") && !this.forceAutoFill)
93
+ value = this.getAttribute("name");
88
94
  this._name = value;
89
95
  this.requestUpdate();
90
96
  }
@@ -103,7 +109,9 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
103
109
  }
104
110
  }
105
111
  getFormPublisher() {
106
- if (!this.formDataProvider) this.formDataProvider = this.getAncestorAttributeValue("formDataProvider");
112
+ if (!this.formDataProvider)
113
+ this.formDataProvider =
114
+ this.getAncestorAttributeValue("formDataProvider");
107
115
  if (this.formDataProvider) {
108
116
  return PublisherManager.get(this.formDataProvider);
109
117
  }
@@ -145,7 +153,7 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
145
153
  if (
146
154
  Objects.isObject(value) &&
147
155
  Object.prototype.hasOwnProperty.call(value, "__value") &&
148
- (value as {_value?: CoreJSType})._value == undefined
156
+ (value as { _value?: CoreJSType })._value == undefined
149
157
  )
150
158
  value = "";
151
159
  if (this._value == value) return;
@@ -156,11 +164,15 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
156
164
  initPublisher() {
157
165
  let formPublisher = this.getFormPublisher();
158
166
  const value =
159
- this.hasAncestorAttribute("initFromPublisher") && this._name && formPublisher[this._name].get()
167
+ this.hasAncestorAttribute("initFromPublisher") &&
168
+ this._name &&
169
+ formPublisher[this._name].get()
160
170
  ? formPublisher[this._name].get()
161
171
  : this.getAttribute("value");
162
- if (this._name && this.publisher) this.publisher[this._name].offAssign(this.onValueAssign);
163
- if (this._name && formPublisher) formPublisher[this._name].offAssign(this.onFormValueAssign);
172
+ if (this._name && this.publisher)
173
+ this.publisher[this._name].offAssign(this.onValueAssign);
174
+ if (this._name && formPublisher)
175
+ formPublisher[this._name].offAssign(this.onFormValueAssign);
164
176
  super.initPublisher();
165
177
  if (!this.name) this._name = this.getAttribute("name");
166
178
  if (!this.value) this._value = this.getAttribute("value");
@@ -194,7 +206,8 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
194
206
  * En appuyant sur la touche "Up", le déplacement inverse est effectué.
195
207
  */
196
208
  addKeyboardNavigation() {
197
- const keyboardLoopIds: string = this.getAncestorAttributeValue("data-keyboard-nav");
209
+ const keyboardLoopIds: string =
210
+ this.getAncestorAttributeValue("data-keyboard-nav");
198
211
  if (!keyboardLoopIds) return;
199
212
 
200
213
  const split = keyboardLoopIds.split(" ");
@@ -214,7 +227,8 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
214
227
  this.addEventListener("keydown", (e) => {
215
228
  const keyboardEvent = e as KeyboardEvent;
216
229
  if (!["ArrowDown", "ArrowUp"].includes(keyboardEvent.key)) return;
217
- const selector = "input:not([disabled]), button:not([disabled]), select:not([disabled]), textarea:not([disabled])";
230
+ const selector =
231
+ "input:not([disabled]), button:not([disabled]), select:not([disabled]), textarea:not([disabled])";
218
232
  const loop = keyboardLoop?.filter((el) => {
219
233
  const child = el.shadowRoot?.querySelector(selector);
220
234
  if (!child) return false;
@@ -244,7 +258,9 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
244
258
  next = loop[index - 1];
245
259
  }
246
260
  }
247
- const elt = next?.shadowRoot?.querySelector(selector) as FormElementInterface | null;
261
+ const elt = next?.shadowRoot?.querySelector(
262
+ selector
263
+ ) as FormElementInterface | null;
248
264
 
249
265
  if (elt && elt.focus) {
250
266
  elt.focus();
@@ -254,15 +270,25 @@ const Form = <T extends Constructor<SubscriberInterface>>(superClass: T) => {
254
270
  });
255
271
  }
256
272
 
273
+ focus() {
274
+ const inputElement = this.shadowRoot?.querySelector(
275
+ "[data-form-element]"
276
+ ) as HTMLInputElement | HTMLSelectElement | HTMLTextAreaElement;
277
+ inputElement?.focus();
278
+ }
279
+
257
280
  connectedCallback(): void {
258
- this.formDataProvider = this.getAncestorAttributeValue("formDataProvider") as string;
281
+ this.formDataProvider = this.getAncestorAttributeValue(
282
+ "formDataProvider"
283
+ ) as string;
259
284
  super.connectedCallback();
260
285
  this.addKeyboardNavigation();
261
286
  }
262
287
 
263
288
  disconnectedCallback() {
264
289
  super.disconnectedCallback();
265
- if (this._name && this.publisher) this.publisher[this._name].offAssign(this.onValueAssign);
290
+ if (this._name && this.publisher)
291
+ this.publisher[this._name].offAssign(this.onValueAssign);
266
292
  const formPublisher = this.getFormPublisher();
267
293
  if (this._name && formPublisher) {
268
294
  formPublisher[this._name].offAssign(this.onFormValueAssign);
@@ -77,8 +77,9 @@ export class PublisherProxy<T = any> {
77
77
  * Supprime les écouteurs associés
78
78
  */
79
79
  delete() {
80
- for (const proxy of this._proxies_.values()) {
81
- proxy.delete();
80
+ for (const key in this._proxies_.keys()) {
81
+ if ((key as string) == "_parent_") continue;
82
+ this._proxies_.get(key)?.delete();
82
83
  }
83
84
  this._invalidateListeners_.clear();
84
85
  this._assignListeners_.clear();
@@ -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>
@@ -2,7 +2,7 @@
2
2
 
3
3
  ## What is Concorde ?
4
4
 
5
- Based on **[lit.dev](https://lit.dev)**, Concorde is a collection of webcomponents made to build shared components, between apps or websites.
5
+ Based on **[lit.dev](https://lit.dev)**, Concorde is a collection of webcomponents made to build shared apps or websites.
6
6
  Develop user interfaces without thinking about the implementation context, where everything is scoped, but preserving graphic consistency by setting the strict minimum of css variables.
7
7
 
8
8
  ## Why and use case
@@ -25,7 +25,7 @@ Webcomponents appeared to be a the perfect solution to guarantee that compatibil
25
25
  * Fetching data, lists, queue with lazyload
26
26
  * Data binding
27
27
  * Simple router, state component, ...
28
- * All ui component, with status variations to build an app with a consistent design
28
+ * And all ui component, with status variants to build an app with a consistent design
29
29
 
30
30
 
31
31
  ## Start a new project easily
@@ -1,64 +1,59 @@
1
- import { html, LitElement } from "lit";
1
+ import { html, LitElement, nothing } from "lit";
2
2
  import { customElement, property } from "lit/decorators.js";
3
- import Subscriber from "@supersoniks/concorde/core/mixins/Subscriber";
4
3
  import { tailwind } from "../tailwind";
5
4
 
6
- @customElement("docs-preview-user-item")
5
+ import Subscriber from "@supersoniks/concorde/core/mixins/Subscriber";
6
+
7
+ @customElement("docs-user")
7
8
  export class user extends Subscriber(LitElement) {
9
+ // add tailwind
8
10
  static styles = [tailwind];
9
11
 
12
+ @property({ type: String }) id = "";
10
13
  @property({ type: String }) avatar = "";
11
14
  @property({ type: String }) first_name = "";
12
15
  @property({ type: String }) email = "";
13
16
  @property({ type: String }) last_name = "";
14
- @property({ type: String }) id = "";
15
17
 
16
18
  render() {
17
- const inList = !!this.props?._metadata_;
18
- const isfirst = this.props?._metadata_?.firstChild;
19
- return html` ${!isfirst && inList
20
- ? html`<div class="border-t my-1 border-neutral-100"></div>`
21
- : ""}
22
- <div
23
- class="flex items-center gap-3 rounded-md hover:bg-neutral-100 -mx-2 p-2"
24
- >
25
- <sonic-image
26
- data-bind=""
27
- src=${this.avatar}
28
- rounded="md"
29
- ratio="1/1"
30
- class="w-16 block"
31
- ></sonic-image>
19
+ return html`<div
20
+ class="flex items-center gap-3 rounded-md hover:bg-neutral-50 -mx-2 p-2"
21
+ >
22
+ <sonic-image
23
+ src=${this.avatar}
24
+ rounded="md"
25
+ ratio="1/1"
26
+ class="w-16 block"
27
+ ></sonic-image>
28
+ <div>
32
29
  <div>
33
- <div class="text-bold">
34
- ${this.first_name} <span class="font-bold">${this.last_name}</span>
35
- </div>
36
- <div class="text-sm text-neutral-400">${this.email}</div>
37
- </div>
38
- <div class="ml-auto relative">
39
- ${this.id == "2" || this.id == "5"
40
- ? html`
41
- <sonic-badge
42
- type="danger"
43
- size="2xs"
44
- class="absolute left-0 -top-1 z-10"
45
- >
46
- ${this.id}</sonic-badge
47
- >
48
- `
49
- : ""}
50
- <sonic-button
51
- data-bind=""
52
- href="mailto:${this.email}"
53
- size="sm"
54
- variant="outline"
55
- shape="circle"
56
- class="relative"
57
- icon
58
- >
59
- <sonic-icon library="iconoir" name="chat-bubble"></sonic-icon>
60
- </sonic-button>
30
+ ${this.first_name} <span class="font-bold">${this.last_name}</span>
61
31
  </div>
62
- </div>`;
32
+ <div class="text-sm text-neutral-400">${this.email}</div>
33
+ </div>
34
+ <div class="ml-auto relative">
35
+ ${this.id == "2" || this.id == "5"
36
+ ? html`
37
+ <sonic-badge
38
+ type="danger"
39
+ size="2xs"
40
+ class="absolute left-0 -top-1 z-10"
41
+ >
42
+ ${this.id}</sonic-badge
43
+ >
44
+ `
45
+ : nothing}
46
+ <sonic-button
47
+ href="mailto:${this.email}"
48
+ size="sm"
49
+ variant="outline"
50
+ shape="circle"
51
+ class="relative"
52
+ icon
53
+ >
54
+ <sonic-icon library="iconoir" name="chat-bubble"></sonic-icon>
55
+ </sonic-button>
56
+ </div>
57
+ </div>`;
63
58
  }
64
59
  }