@hotosm/ui 0.2.0-b2 → 0.2.0-b4

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.
@@ -4,16 +4,14 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import "../theme/hot.css";
8
- import '@shoelace-style/shoelace/dist/themes/light.css';
9
- import '@shoelace-style/shoelace/dist/themes/dark.css';
7
+ import "../../theme/sl-custom.css";
10
8
  import '@shoelace-style/shoelace/dist/components/button/button.js';
11
9
  import '@shoelace-style/shoelace/dist/components/button-group/button-group.js';
12
10
  import '@shoelace-style/shoelace/dist/components/icon/icon.js';
13
11
  import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js';
14
12
  import { LitElement, css, html } from "lit";
15
13
  import { property } from "lit/decorators.js";
16
- import registerBundledIcons from '../components/icons';
14
+ import registerBundledIcons from '../../components/icons';
17
15
  registerBundledIcons();
18
16
  // import { cva } from "class-variance-authority";
19
17
  // const toolbarStyle = cva(
@@ -37,35 +35,35 @@ export class Toolbar extends LitElement {
37
35
  // As the original event is also named 'click'
38
36
  // stop propagation of the original event
39
37
  e.stopPropagation();
40
- this.dispatchEvent(new Event("hot-undo-click"));
38
+ this.dispatchEvent(new Event("undo"));
41
39
  };
42
40
  this.redo = (e) => {
43
41
  e.stopPropagation();
44
- this.dispatchEvent(new Event("hot-redo-click"));
42
+ this.dispatchEvent(new Event("redo"));
45
43
  };
46
44
  this.bold = (e) => {
47
45
  e.stopPropagation();
48
- this.dispatchEvent(new Event("hot-bold-click"));
46
+ this.dispatchEvent(new Event("bold"));
49
47
  };
50
48
  this.italic = (e) => {
51
49
  e.stopPropagation();
52
- this.dispatchEvent(new Event("hot-italic-click"));
50
+ this.dispatchEvent(new Event("italic"));
53
51
  };
54
52
  this.underline = (e) => {
55
53
  e.stopPropagation();
56
- this.dispatchEvent(new Event("hot-underline-click"));
54
+ this.dispatchEvent(new Event("underline"));
57
55
  };
58
56
  this.alignLeft = (e) => {
59
57
  e.stopPropagation();
60
- this.dispatchEvent(new Event("hot-leftalign-click"));
58
+ this.dispatchEvent(new Event("leftalign"));
61
59
  };
62
60
  this.alignCenter = (e) => {
63
61
  e.stopPropagation();
64
- this.dispatchEvent(new Event("hot-centeralign-click"));
62
+ this.dispatchEvent(new Event("centeralign"));
65
63
  };
66
64
  this.alignRight = (e) => {
67
65
  e.stopPropagation();
68
- this.dispatchEvent(new Event("hot-rightalign-click"));
66
+ this.dispatchEvent(new Event("rightalign"));
69
67
  };
70
68
  }
71
69
  // class=${toolbarStyle({
@@ -0,0 +1,128 @@
1
+ import "../../theme/sl-custom.css";
2
+
3
+ import '@shoelace-style/shoelace/dist/components/button/button.js';
4
+ import '@shoelace-style/shoelace/dist/components/button-group/button-group.js';
5
+ import '@shoelace-style/shoelace/dist/components/icon/icon.js';
6
+ import '@shoelace-style/shoelace/dist/components/tooltip/tooltip.js';
7
+
8
+ import { LitElement, css, html, unsafeCSS } from "lit";
9
+ import { property } from "lit/decorators.js";
10
+
11
+ import registerBundledIcons from '../../components/icons';
12
+
13
+ registerBundledIcons();
14
+
15
+ // import { cva } from "class-variance-authority";
16
+
17
+ // const toolbarStyle = cva(
18
+ // "some-css-var",
19
+ // {
20
+ // variants: {
21
+ // someProperty: {
22
+ // true: "some-css-var",
23
+ // false: "some-css-var",
24
+ // },
25
+ // },
26
+ // },
27
+ // );
28
+
29
+ export class Toolbar extends LitElement {
30
+ @property() name = "hot-toolbar";
31
+
32
+ /** Change the position of the tooltips relative to buttons. */
33
+ @property({ type: String, attribute: "tooltip-position" }) tooltipPosition = "top";
34
+
35
+ static styles = [
36
+ css`
37
+ @unocss-placeholder;
38
+ `,
39
+ // unsafeCSS(reset),
40
+ ];
41
+
42
+ // class=${toolbarStyle({
43
+ // someProperty: this.someProperty,
44
+ // })}
45
+ protected render() {
46
+ return html`
47
+ <div class="button-group-toolbar">
48
+ ${this.renderButtonGroup('History', [
49
+ { content: 'Undo', icon: 'arrow-counterclockwise', label: 'Undo', action: this.undo },
50
+ { content: 'Redo', icon: 'arrow-clockwise', label: 'Redo', action: this.redo }
51
+ ])}
52
+ ${this.renderButtonGroup('Formatting', [
53
+ { content: 'Bold', icon: 'type-bold', label: 'Bold', action: this.bold },
54
+ { content: 'Italic', icon: 'type-italic', label: 'Italic', action: this.italic },
55
+ { content: 'Underline', icon: 'type-underline', label: 'Underline', action: this.underline }
56
+ ])}
57
+ ${this.renderButtonGroup('Alignment', [
58
+ { content: 'Align Left', icon: 'justify-left', label: 'Align Left', action: this.alignLeft },
59
+ { content: 'Align Center', icon: 'justify', label: 'Align Center', action: this.alignCenter },
60
+ { content: 'Align Right', icon: 'justify-right', label: 'Align Right', action: this.alignRight }
61
+ ])}
62
+ </div>
63
+ `;
64
+ }
65
+
66
+ private renderButtonGroup(label: string, buttons: Array<{ content: string, icon: string, label: string, action?: (e: MouseEvent) => void }>) {
67
+ return html`
68
+ <sl-button-group label=${label}>
69
+ ${buttons.map(button => this.renderButton(button))}
70
+ </sl-button-group>
71
+ `;
72
+ }
73
+
74
+ private renderButton({ content, icon, label, action }: { content: string, icon: string, label: string, action?: (e: MouseEvent) => void }) {
75
+ return html`
76
+ <sl-tooltip content=${content} placement="${this.tooltipPosition}">
77
+ <sl-button @click=${action ?? (() => {})}><sl-icon library="bundled" name=${icon} label=${label}></sl-icon></sl-button>
78
+ </sl-tooltip>
79
+ `;
80
+ }
81
+
82
+ private readonly undo = (e: MouseEvent) => {
83
+ // As the original event is also named 'click'
84
+ // stop propagation of the original event
85
+ e.stopPropagation();
86
+ this.dispatchEvent(new Event("undo"));
87
+ }
88
+
89
+ private readonly redo = (e: MouseEvent) => {
90
+ e.stopPropagation();
91
+ this.dispatchEvent(new Event("redo"));
92
+ }
93
+
94
+ private readonly bold = (e: MouseEvent) => {
95
+ e.stopPropagation();
96
+ this.dispatchEvent(new Event("bold"));
97
+ }
98
+
99
+ private readonly italic = (e: MouseEvent) => {
100
+ e.stopPropagation();
101
+ this.dispatchEvent(new Event("italic"));
102
+ }
103
+
104
+ private readonly underline = (e: MouseEvent) => {
105
+ e.stopPropagation();
106
+ this.dispatchEvent(new Event("underline"));
107
+ }
108
+
109
+ private readonly alignLeft = (e: MouseEvent) => {
110
+ e.stopPropagation();
111
+ this.dispatchEvent(new Event("leftalign"));
112
+ }
113
+
114
+ private readonly alignCenter = (e: MouseEvent) => {
115
+ e.stopPropagation();
116
+ this.dispatchEvent(new Event("centeralign"));
117
+ }
118
+
119
+ private readonly alignRight = (e: MouseEvent) => {
120
+ e.stopPropagation();
121
+ this.dispatchEvent(new Event("rightalign"));
122
+ }
123
+ }
124
+
125
+ export default Toolbar;
126
+
127
+ // Define web component
128
+ customElements.define("hot-toolbar", Toolbar);
@@ -1,6 +1,4 @@
1
- import "../theme/hot.css";
2
- import '@shoelace-style/shoelace/dist/themes/light.css';
3
- import '@shoelace-style/shoelace/dist/themes/dark.css';
1
+ import "../../theme/sl-custom.css";
4
2
  import '@shoelace-style/shoelace/dist/components/alert/alert.js';
5
3
  import { LitElement } from "lit";
6
4
  declare global {
@@ -4,13 +4,11 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import "../theme/hot.css";
8
- import '@shoelace-style/shoelace/dist/themes/light.css';
9
- import '@shoelace-style/shoelace/dist/themes/dark.css';
7
+ import "../../theme/sl-custom.css";
10
8
  import '@shoelace-style/shoelace/dist/components/alert/alert.js';
11
9
  import { LitElement, css, html } from "lit";
12
10
  import { property, state } from "lit/decorators.js";
13
- import registerBundledIcons from '../components/icons';
11
+ import registerBundledIcons from '../../components/icons';
14
12
  registerBundledIcons();
15
13
  export class Tracking extends LitElement {
16
14
  constructor() {
@@ -40,7 +38,7 @@ export class Tracking extends LitElement {
40
38
  and measure traffic usage and activity. You can learn about how we use the data
41
39
  about your visit or information you provide reading our
42
40
  <a
43
- id="hot-red-text"
41
+ style="color: #d63f3f;"
44
42
  href="https://www.hotosm.org/privacy"
45
43
  target="_blank"
46
44
  rel="noopener noreferrer"
@@ -48,8 +46,8 @@ export class Tracking extends LitElement {
48
46
  By clicking "I Agree", you consent to the use of cookies.
49
47
  </p>
50
48
 
51
- <sl-button @click=${this._setAgree}>I Agree</sl-button>
52
- <sl-button @click=${this._setDisagree}>I Do Not Agree</sl-button>
49
+ <sl-button @click=${(e) => { this._setAgree(e); }}>I Agree</sl-button>
50
+ <sl-button @click=${(e) => { this._setDisagree(e); }}>I Do Not Agree</sl-button>
53
51
  </sl-alert>`;
54
52
  }
55
53
  _setAgree(_e) {
@@ -76,7 +74,7 @@ export class Tracking extends LitElement {
76
74
  super.connectedCallback();
77
75
  // Close and halt execution if wrong domain
78
76
  if (!this.force && window.location.hostname !== this.domain) {
79
- console.warn('Matomo init failed. Provided domain does not match current domain.');
77
+ console.warn(`Matomo init failed. ${window.location.hostname} does not match ${this.domain}.`);
80
78
  this.isOpen = false;
81
79
  return;
82
80
  }
@@ -133,10 +131,7 @@ Tracking.styles = [
133
131
  #tracking-header {
134
132
  font-weight: var(--sl-font-weight-bold);
135
133
  font-size: var(--sl-font-size-large);
136
- color: #d63f3f;
137
- }
138
- #hot-red-text {
139
- color: #d63f3f;
134
+ text-align: center;
140
135
  }
141
136
  sl-alert::part(base) {
142
137
  position: absolute;
@@ -145,6 +140,7 @@ Tracking.styles = [
145
140
  transform: translateX(-50%);
146
141
  z-index: 1000;
147
142
  width: 80vw;
143
+ text-align: center;
148
144
  }
149
145
  `
150
146
  ];
@@ -0,0 +1,173 @@
1
+ import "../../theme/sl-custom.css";
2
+
3
+ import '@shoelace-style/shoelace/dist/components/alert/alert.js';
4
+
5
+ import { LitElement, css, html, unsafeCSS } from "lit";
6
+ import { property, state } from "lit/decorators.js";
7
+
8
+ import registerBundledIcons from '../../components/icons';
9
+
10
+ registerBundledIcons();
11
+
12
+ declare global {
13
+ interface Window {
14
+ _paq: any[];
15
+ }
16
+ }
17
+
18
+ export class Tracking extends LitElement {
19
+ @property() name = "hot-tracking";
20
+
21
+ /** The Matomo site id for tracking. */
22
+ @property({ type: String, attribute: "site-id" }) siteId: string = "";
23
+
24
+ /** The domains to apply tracking. */
25
+ @property({ type: String }) domain: string = "";
26
+
27
+ /** Force display the banner. */
28
+ @property({ type: Boolean }) force: boolean = false;
29
+
30
+ @state() isOpen: boolean = true;
31
+
32
+ static styles = [
33
+ css`
34
+ @unocss-placeholder;
35
+ `,
36
+
37
+ // Temp styles until UnoCSS setup
38
+ css`
39
+ #tracking-header {
40
+ font-weight: var(--sl-font-weight-bold);
41
+ font-size: var(--sl-font-size-large);
42
+ text-align: center;
43
+ }
44
+ sl-alert::part(base) {
45
+ position: absolute;
46
+ bottom: 20px;
47
+ left: 50%;
48
+ transform: translateX(-50%);
49
+ z-index: 1000;
50
+ width: 80vw;
51
+ text-align: center;
52
+ }
53
+ `
54
+ ];
55
+
56
+ protected render() {
57
+ return html`<sl-alert
58
+ variant="danger"
59
+ ?open=${this.isOpen}
60
+ >
61
+ <sl-icon id="hot-red-text" library="bundled" slot="icon" name="info-circle"></sl-icon>
62
+
63
+ <p id="tracking-header">
64
+ About the information we collect
65
+ </p>
66
+
67
+ <p>
68
+ We use cookies and similar technologies to recognize and analyze your visits,
69
+ and measure traffic usage and activity. You can learn about how we use the data
70
+ about your visit or information you provide reading our
71
+ <a
72
+ style="color: #d63f3f;"
73
+ href="https://www.hotosm.org/privacy"
74
+ target="_blank"
75
+ rel="noopener noreferrer"
76
+ >privacy policy</a>.
77
+ By clicking "I Agree", you consent to the use of cookies.
78
+ </p>
79
+
80
+ <sl-button @click=${(e: MouseEvent) => {this._setAgree(e)}}>I Agree</sl-button>
81
+ <sl-button @click=${(e: MouseEvent) => {this._setDisagree(e)}}>I Do Not Agree</sl-button>
82
+ </sl-alert>`;
83
+ }
84
+
85
+ private _setAgree(_e: MouseEvent) {
86
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
87
+ const _paq = (window._paq = window._paq || []);
88
+ if (_paq.length === 0) return;
89
+
90
+ _paq.push(['rememberConsentGiven']);
91
+ this.isOpen = false;
92
+ localStorage.setItem(`${this.siteId}-matomo-agree`, 'true');
93
+ this.dispatchEvent(new Event('agree', {bubbles: true, composed: true}));
94
+ }
95
+
96
+ private _setDisagree(_e: MouseEvent) {
97
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
98
+ const _paq = (window._paq = window._paq || []);
99
+ if (_paq.length === 0) return;
100
+
101
+ _paq.push(['forgetConsentGiven']);
102
+ this.isOpen = false;
103
+ localStorage.setItem(`${this.siteId}-matomo-agree`, 'false');
104
+ this.dispatchEvent(new Event('disagree', {bubbles: true, composed: true}));
105
+ }
106
+
107
+ connectedCallback() {
108
+ super.connectedCallback();
109
+
110
+ // Close and halt execution if wrong domain
111
+ if (!this.force && window.location.hostname !== this.domain) {
112
+ console.warn(`Matomo init failed. ${window.location.hostname} does not match ${this.domain}.`);
113
+ this.isOpen = false;
114
+ return;
115
+ }
116
+
117
+ const matomoTrackingId = this.siteId;
118
+
119
+ // Close and halt execution if siteId or domain not set
120
+ if (!this.force && (matomoTrackingId.length === 0 || this.domain.length === 0)) {
121
+ console.warn('Matomo init failed. No site id or domains provided.');
122
+ this.isOpen = false;
123
+ return;
124
+ }
125
+
126
+ // Close and halt execution if already disagreed
127
+ const consent = localStorage.getItem(`${this.siteId}-matomo-agree`);
128
+ if (consent === 'false') {
129
+ this.isOpen = false;
130
+ return;
131
+ }
132
+
133
+ // Close prompt only if already agreed, continue
134
+ if (consent === 'true') {
135
+ this.isOpen = false;
136
+ }
137
+
138
+ console.log(`Setting Matomo tracking for site=${matomoTrackingId} domain=${this.domain}`);
139
+
140
+ // eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
141
+ const _paq = (window._paq = window._paq || []);
142
+
143
+ // tracker methods like "setCustomDimension" should be called before "trackPageView"
144
+ _paq.push(['requireConsent']);
145
+ _paq.push(['setDomains', [this.domain]]);
146
+ _paq.push(['trackPageView']);
147
+ _paq.push(['enableLinkTracking']); // Tracks downloads
148
+ _paq.push(['trackVisibleContentImpressions']); // Tracks content
149
+
150
+ (function () {
151
+ const u = '//matomo.hotosm.org/';
152
+ _paq.push(['setTrackerUrl', u + 'matomo.php']);
153
+ _paq.push(['setSiteId', matomoTrackingId]);
154
+
155
+ const d = document;
156
+ const g = d.createElement('script');
157
+ const s = d.getElementsByTagName('script')[0];
158
+
159
+ if (s?.parentNode != null) {
160
+ g.async = true;
161
+ g.src = u + 'matomo.js';
162
+ s.parentNode.insertBefore(g, s);
163
+ } else {
164
+ console.warn('Script insertion failed. Parent node is null.');
165
+ }
166
+ })();
167
+ }
168
+ }
169
+
170
+ export default Tracking;
171
+
172
+ // Define web component
173
+ customElements.define("hot-tracking", Tracking);