@kompasid/lit-web-components 0.9.19 → 0.9.21

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.
@@ -1,229 +1,87 @@
1
1
  import { __decorate } from "tslib";
2
- /* eslint-disable lit-a11y/click-events-have-key-events */
3
- import { html, css, LitElement } from 'lit';
2
+ import { LitElement, html, css } from 'lit';
4
3
  import { customElement, property, state } from 'lit/decorators.js';
4
+ import { repeat } from 'lit/directives/repeat.js';
5
5
  import { unsafeSVG } from 'lit/directives/unsafe-svg.js';
6
6
  import { TWStyles } from '../../../tailwind/tailwind.js';
7
7
  import { getFontAwesomeIcon } from '../../utils/fontawesome-setup.js';
8
8
  import { decodeSpecialChars } from '../../utils/decodeSpecialChars.js';
9
9
  import { timedContent } from '../../utils/timedContent.js';
10
+ // Importing the data fetch functions
11
+ import { fetchExternalLinks, fetchSidebarData, } from './SidebarDataController.js';
10
12
  let KompasMenuSideBar = class KompasMenuSideBar extends LitElement {
11
13
  constructor() {
12
14
  super(...arguments);
13
- this.hasSlotContent = false;
14
- this.dataExternal = [];
15
+ /**
16
+ * Props
17
+ * property kompasProSubscription untuk menghandle apakah user sudah login atau belum
18
+ */
15
19
  this.isDark = false;
20
+ this.isProductionMode = false;
21
+ this.subscriptionPackage = '';
22
+ this.dataExternal = [];
16
23
  this.dataSidebar = {
24
+ bundles: [],
17
25
  feature: [],
18
26
  category: [],
19
27
  lainnya: [],
20
28
  };
21
- this.expandedSlug = null;
22
29
  this.showNavBar = false;
23
- this.toggleNavSidebar = (e) => {
24
- e.stopPropagation(); // prevent bubbling
25
- this.showNavBar = !this.showNavBar;
26
- };
27
- }
28
- firstUpdated() {
29
- var _a;
30
- const slot = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('slot');
31
- const assignedNodes = slot.assignedNodes({ flatten: true });
32
- this.hasSlotContent = assignedNodes.length > 0;
30
+ this.expandedSlug = null;
31
+ this.hasSlotContent = false;
33
32
  }
33
+ // Fetch data when the component is connected to the DOM
34
34
  async connectedCallback() {
35
35
  super.connectedCallback();
36
- try {
37
- await this.fetchExternal();
38
- }
39
- catch (error) {
40
- this.handleFetchError(error);
41
- }
36
+ await this.loadData();
42
37
  }
43
- handleFetchError(error) {
44
- const errorMessage = error instanceof Error ? error.message : 'Kesalahan tidak diketahui';
45
- alert(`Terjadi kesalahan: ${errorMessage}`);
38
+ hasKompasOnePackage() {
39
+ var _a;
40
+ return (_a = this.subscriptionPackage) === null || _a === void 0 ? void 0 : _a.split(' ').some(pkg => pkg.includes('kompas-one'));
46
41
  }
47
- async fetchExternal() {
48
- var _a, _b, _c;
49
- // External
50
- const endpointExternal = `https://cdn-dev-www.kompas.id/assets/json/ApiMenuExternalLinkV2.json`;
51
- const response = await fetch(endpointExternal, {
52
- headers: {
53
- 'Content-Type': 'application/json',
54
- },
42
+ hasKompasProPackage() {
43
+ var _a;
44
+ return (_a = this.subscriptionPackage) === null || _a === void 0 ? void 0 : _a.split(' ').some(pkg => pkg.includes('kompas-pro'));
45
+ }
46
+ filterBundles(bundles) {
47
+ return bundles
48
+ .filter(b => b.isShow)
49
+ .map(b => {
50
+ if (b.name === 'Kompas One') {
51
+ return {
52
+ ...b,
53
+ children: this.hasKompasOnePackage() ? b.children : [],
54
+ };
55
+ }
56
+ if (b.name === 'Kompas Pro') {
57
+ return {
58
+ ...b,
59
+ children: this.hasKompasProPackage() ? b.children : [],
60
+ };
61
+ }
62
+ return b;
55
63
  });
56
- const resultExternal = await response.json();
57
- // eslint-disable-next-line no-undef
58
- if (!resultExternal || !Array.isArray(resultExternal)) {
59
- console.error('Error: resultExternal.result is undefined or not an array', resultExternal);
60
- this.dataExternal = []; // Ensure dataExternal is an empty array instead of undefined
61
- }
62
- else {
63
- this.dataExternal = resultExternal.map((externalLink) => {
64
- var _a, _b, _c, _d, _e, _f, _g;
65
- return ({
66
- external: (_a = externalLink.external) !== null && _a !== void 0 ? _a : false,
67
- gtmClass: (_b = externalLink.gtmClass) !== null && _b !== void 0 ? _b : '',
68
- icon: (_c = externalLink.icon) !== null && _c !== void 0 ? _c : null,
69
- iconify: (_d = externalLink.iconify) !== null && _d !== void 0 ? _d : null,
70
- isNew: (_e = externalLink.isNew) !== null && _e !== void 0 ? _e : false,
71
- name: (_f = externalLink.name) !== null && _f !== void 0 ? _f : '',
72
- url: (_g = externalLink.url) !== null && _g !== void 0 ? _g : '',
73
- });
74
- });
64
+ }
65
+ // Function to load the data using async API calls
66
+ async loadData() {
67
+ try {
68
+ const [extData, sbData] = await Promise.all([
69
+ fetchExternalLinks(this.isProductionMode),
70
+ fetchSidebarData(this.isProductionMode),
71
+ ]);
72
+ this.dataExternal = extData;
73
+ this.dataSidebar = {
74
+ ...sbData,
75
+ bundles: this.filterBundles(sbData.bundles),
76
+ };
75
77
  }
76
- // Sidebar
77
- const endpointSidebar = `https://cdn-dev-www.kompas.id/assets/json/ApiMenuSideV3.json`;
78
- const responseSidebar = await fetch(endpointSidebar, {
79
- headers: {
80
- 'Content-Type': 'application/json',
81
- },
82
- });
83
- const resultSidebar = await responseSidebar.json();
84
- // Validate the structure of the response
85
- if (!resultSidebar || typeof resultSidebar !== 'object') {
86
- console.error('Invalid response format:', resultSidebar);
87
- return;
78
+ catch (error) {
79
+ console.error('Error loading data:', error);
88
80
  }
89
- // Convert object to an array
90
- const sidebarArray = Object.values(resultSidebar);
91
- const [featureArray, categoryArray, othersArray] = sidebarArray;
92
- const features = (_a = featureArray === null || featureArray === void 0 ? void 0 : featureArray.map((item) => {
93
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
94
- return ({
95
- href: (_a = item === null || item === void 0 ? void 0 : item.href) !== null && _a !== void 0 ? _a : '',
96
- external: (_b = item === null || item === void 0 ? void 0 : item.external) !== null && _b !== void 0 ? _b : false,
97
- icon: (_c = item === null || item === void 0 ? void 0 : item.icon) !== null && _c !== void 0 ? _c : null,
98
- iconify: (_d = item === null || item === void 0 ? void 0 : item.iconify) !== null && _d !== void 0 ? _d : null,
99
- name: (_e = item === null || item === void 0 ? void 0 : item.name) !== null && _e !== void 0 ? _e : '',
100
- slug: (_f = item === null || item === void 0 ? void 0 : item.slug) !== null && _f !== void 0 ? _f : '',
101
- redDot: [
102
- {
103
- start: (_h = (_g = item === null || item === void 0 ? void 0 : item.redDot) === null || _g === void 0 ? void 0 : _g.start) !== null && _h !== void 0 ? _h : '',
104
- end: (_k = (_j = item === null || item === void 0 ? void 0 : item.redDot) === null || _j === void 0 ? void 0 : _j.end) !== null && _k !== void 0 ? _k : '',
105
- },
106
- ],
107
- children: Array.isArray(item === null || item === void 0 ? void 0 : item.children)
108
- ? item.children.map((child) => {
109
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
110
- return ({
111
- href: (_a = child === null || child === void 0 ? void 0 : child.href) !== null && _a !== void 0 ? _a : '',
112
- external: (_b = child === null || child === void 0 ? void 0 : child.external) !== null && _b !== void 0 ? _b : false,
113
- icon: (_c = child === null || child === void 0 ? void 0 : child.icon) !== null && _c !== void 0 ? _c : '',
114
- iconify: (_d = child === null || child === void 0 ? void 0 : child.iconify) !== null && _d !== void 0 ? _d : '',
115
- name: (_e = child === null || child === void 0 ? void 0 : child.name) !== null && _e !== void 0 ? _e : '',
116
- slug: (_f = child === null || child === void 0 ? void 0 : child.slug) !== null && _f !== void 0 ? _f : '',
117
- redDot: [
118
- {
119
- start: (_h = (_g = child === null || child === void 0 ? void 0 : child.redDot) === null || _g === void 0 ? void 0 : _g.start) !== null && _h !== void 0 ? _h : '',
120
- end: (_k = (_j = child === null || child === void 0 ? void 0 : child.redDot) === null || _j === void 0 ? void 0 : _j.end) !== null && _k !== void 0 ? _k : '',
121
- },
122
- ],
123
- });
124
- })
125
- : [],
126
- });
127
- })) !== null && _a !== void 0 ? _a : [];
128
- // Map category data
129
- const categories = (_b = categoryArray === null || categoryArray === void 0 ? void 0 : categoryArray.map((item) => {
130
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
131
- return ({
132
- href: (_a = item === null || item === void 0 ? void 0 : item.href) !== null && _a !== void 0 ? _a : '',
133
- external: (_b = item === null || item === void 0 ? void 0 : item.external) !== null && _b !== void 0 ? _b : false,
134
- icon: (_c = item === null || item === void 0 ? void 0 : item.icon) !== null && _c !== void 0 ? _c : null,
135
- iconify: (_d = item === null || item === void 0 ? void 0 : item.iconify) !== null && _d !== void 0 ? _d : null,
136
- name: (_e = item === null || item === void 0 ? void 0 : item.name) !== null && _e !== void 0 ? _e : '',
137
- slug: (_f = item === null || item === void 0 ? void 0 : item.slug) !== null && _f !== void 0 ? _f : '',
138
- redDot: [
139
- {
140
- start: (_h = (_g = item === null || item === void 0 ? void 0 : item.redDot) === null || _g === void 0 ? void 0 : _g.start) !== null && _h !== void 0 ? _h : '',
141
- end: (_k = (_j = item === null || item === void 0 ? void 0 : item.redDot) === null || _j === void 0 ? void 0 : _j.end) !== null && _k !== void 0 ? _k : '',
142
- },
143
- ],
144
- children: Array.isArray(item === null || item === void 0 ? void 0 : item.children)
145
- ? item.children.map((child) => {
146
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
147
- return ({
148
- href: (_a = child === null || child === void 0 ? void 0 : child.href) !== null && _a !== void 0 ? _a : '',
149
- external: (_b = child === null || child === void 0 ? void 0 : child.external) !== null && _b !== void 0 ? _b : false,
150
- icon: (_c = child === null || child === void 0 ? void 0 : child.icon) !== null && _c !== void 0 ? _c : '',
151
- iconify: (_d = child === null || child === void 0 ? void 0 : child.iconify) !== null && _d !== void 0 ? _d : '',
152
- name: (_e = child === null || child === void 0 ? void 0 : child.name) !== null && _e !== void 0 ? _e : '',
153
- slug: (_f = child === null || child === void 0 ? void 0 : child.slug) !== null && _f !== void 0 ? _f : '',
154
- redDot: [
155
- {
156
- start: (_h = (_g = child === null || child === void 0 ? void 0 : child.redDot) === null || _g === void 0 ? void 0 : _g.start) !== null && _h !== void 0 ? _h : '',
157
- end: (_k = (_j = child === null || child === void 0 ? void 0 : child.redDot) === null || _j === void 0 ? void 0 : _j.end) !== null && _k !== void 0 ? _k : '',
158
- },
159
- ],
160
- });
161
- })
162
- : [],
163
- });
164
- })) !== null && _b !== void 0 ? _b : [];
165
- // Map others data
166
- const others = (_c = othersArray === null || othersArray === void 0 ? void 0 : othersArray.map((item) => {
167
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
168
- return ({
169
- href: (_a = item === null || item === void 0 ? void 0 : item.href) !== null && _a !== void 0 ? _a : '',
170
- external: (_b = item === null || item === void 0 ? void 0 : item.external) !== null && _b !== void 0 ? _b : false,
171
- icon: (_c = item === null || item === void 0 ? void 0 : item.icon) !== null && _c !== void 0 ? _c : null,
172
- iconify: (_d = item === null || item === void 0 ? void 0 : item.iconify) !== null && _d !== void 0 ? _d : null,
173
- name: (_e = item === null || item === void 0 ? void 0 : item.name) !== null && _e !== void 0 ? _e : '',
174
- slug: (_f = item === null || item === void 0 ? void 0 : item.slug) !== null && _f !== void 0 ? _f : '',
175
- redDot: [
176
- {
177
- start: (_h = (_g = item === null || item === void 0 ? void 0 : item.redDot) === null || _g === void 0 ? void 0 : _g.start) !== null && _h !== void 0 ? _h : '',
178
- end: (_k = (_j = item === null || item === void 0 ? void 0 : item.redDot) === null || _j === void 0 ? void 0 : _j.end) !== null && _k !== void 0 ? _k : '',
179
- },
180
- ],
181
- children: Array.isArray(item === null || item === void 0 ? void 0 : item.children)
182
- ? item.children.map((child) => {
183
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
184
- return ({
185
- href: (_a = child === null || child === void 0 ? void 0 : child.href) !== null && _a !== void 0 ? _a : '',
186
- external: (_b = child === null || child === void 0 ? void 0 : child.external) !== null && _b !== void 0 ? _b : false,
187
- icon: (_c = child === null || child === void 0 ? void 0 : child.icon) !== null && _c !== void 0 ? _c : '',
188
- iconify: (_d = child === null || child === void 0 ? void 0 : child.iconify) !== null && _d !== void 0 ? _d : '',
189
- name: (_e = child === null || child === void 0 ? void 0 : child.name) !== null && _e !== void 0 ? _e : '',
190
- slug: (_f = child === null || child === void 0 ? void 0 : child.slug) !== null && _f !== void 0 ? _f : '',
191
- redDot: [
192
- {
193
- start: (_h = (_g = child === null || child === void 0 ? void 0 : child.redDot) === null || _g === void 0 ? void 0 : _g.start) !== null && _h !== void 0 ? _h : '',
194
- end: (_k = (_j = child === null || child === void 0 ? void 0 : child.redDot) === null || _j === void 0 ? void 0 : _j.end) !== null && _k !== void 0 ? _k : '',
195
- },
196
- ],
197
- });
198
- })
199
- : [],
200
- });
201
- })) !== null && _c !== void 0 ? _c : [];
202
- this.dataSidebar = {
203
- feature: features,
204
- category: categories,
205
- lainnya: others,
206
- };
207
- this.requestUpdate();
208
- }
209
- renderChips() {
210
- const chips = [];
211
- chips.push(html `
212
- <div class="flex">
213
- <div
214
- class="py-0.5 px-1.5 rounded-full"
215
- style="position: relative; display: inline-flex; background-color:#D71920;"
216
- >
217
- <span class="font-bold font-sans text-xs text-white capitalize"
218
- >Baru</span
219
- >
220
- </div>
221
- </div>
222
- `);
223
- return chips;
224
81
  }
225
- hasChildren(item) {
226
- return Array.isArray(item === null || item === void 0 ? void 0 : item.children) && item.children.length > 0;
82
+ toggleNavSidebar(e) {
83
+ e.stopPropagation();
84
+ this.showNavBar = !this.showNavBar;
227
85
  }
228
86
  rubricClicked(item, event) {
229
87
  if (event) {
@@ -234,51 +92,174 @@ let KompasMenuSideBar = class KompasMenuSideBar extends LitElement {
234
92
  }
235
93
  // add data layer here
236
94
  }
95
+ hasChildren(item) {
96
+ return Array.isArray(item.children) && item.children.length > 0;
97
+ }
237
98
  toggleChildren(item) {
238
99
  this.expandedSlug = this.expandedSlug === item.slug ? null : item.slug;
239
100
  }
101
+ renderItem(item, padClass) {
102
+ var _a, _b, _c;
103
+ return html `
104
+ <div class="w-full font-sans text-black">
105
+ <div
106
+ class="flex items-center justify-between text-sm font-medium ${padClass} transition-all cursor-pointer"
107
+ role="button"
108
+ tabindex="0"
109
+ @click=${(e) => this.rubricClicked(item, e)}
110
+ @keydown=${(e) => {
111
+ if (e.key === 'Enter')
112
+ this.rubricClicked(item, e);
113
+ }}
114
+ >
115
+ <div
116
+ class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center space-x-3"
117
+ >
118
+ ${item.iconSrc
119
+ ? html `<div class="flex">
120
+ <img
121
+ src="${item.iconSrc}"
122
+ alt="Kompas.id"
123
+ scale="0"
124
+ class="block w-5"
125
+ />
126
+ </div>`
127
+ : ''}
128
+ <span class="font-bold">${decodeSpecialChars(item.name)}</span>
129
+ ${timedContent((_a = item.redDot.start) !== null && _a !== void 0 ? _a : '', (_b = item.redDot.end) !== null && _b !== void 0 ? _b : '')
130
+ ? html `<span
131
+ class="bg-orange-400 h‑2 w‑2 rounded-full relative -top-[12px] shrink-0"
132
+ ></span>`
133
+ : ''}
134
+ </div>
135
+ ${this.hasChildren(item)
136
+ ? html `
137
+ <span
138
+ class="flex justify-center items-center rounded my‑1 py‑4 w‑10 h‑10 cursor‑pointer text-grey-400"
139
+ role="button"
140
+ tabindex="0"
141
+ @click=${(e) => {
142
+ e.stopPropagation();
143
+ this.toggleChildren(item);
144
+ }}
145
+ @keydown=${(e) => {
146
+ if (e.key === 'Enter') {
147
+ e.stopPropagation();
148
+ this.toggleChildren(item);
149
+ }
150
+ }}
151
+ >
152
+ ${unsafeSVG(getFontAwesomeIcon('fas', this.expandedSlug === item.slug
153
+ ? 'chevron-up'
154
+ : 'chevron-down', 12, 12))}
155
+ </span>
156
+ `
157
+ : null}
158
+ </div>
159
+
160
+ ${this.hasChildren(item) && this.expandedSlug === item.slug
161
+ ? html `<div
162
+ class="${padClass.includes('px-6')
163
+ ? 'pt‑1 pb‑2 space-y‑1 text-black'
164
+ : 'pl‑14 pt‑1 pb‑2 space-y‑1 text-black'}"
165
+ >
166
+ ${repeat((_c = item.children) !== null && _c !== void 0 ? _c : [], (c) => c.slug, (child) => {
167
+ var _a, _b;
168
+ return html `
169
+ <div
170
+ role="button"
171
+ tabindex="0"
172
+ class="flex items-center justify-between text-sm font-medium px-6 transition-all cursor-pointer"
173
+ @click=${() => this.rubricClicked(child)}
174
+ @keydown=${(e) => {
175
+ if (e.key === 'Enter')
176
+ this.rubricClicked(child, e);
177
+ }}
178
+ >
179
+ <div
180
+ class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center pl-8"
181
+ >
182
+ ${decodeSpecialChars(child.name)}
183
+ ${timedContent((_a = child.redDot.start) !== null && _a !== void 0 ? _a : '', (_b = child.redDot.end) !== null && _b !== void 0 ? _b : '')
184
+ ? html `<span
185
+ class="bg-orange-400 h‑2 w‑2 rounded-full relative -top-[12px] shrink-0"
186
+ ></span>`
187
+ : ''}
188
+ </div>
189
+ <span class="ml-auto text-grey-400">
190
+ ${child.external
191
+ ? unsafeSVG(getFontAwesomeIcon('fas', 'external-link', 16, 16))
192
+ : ''}
193
+ </span>
194
+ </div>
195
+ `;
196
+ })}
197
+ </div>`
198
+ : ''}
199
+ </div>
200
+ `;
201
+ }
202
+ renderSection(title, items, padClass) {
203
+ if (!items || items.length === 0)
204
+ return null; // skip if empty data
205
+ return html `
206
+ ${title
207
+ ? html `<span class="text-sm text-grey-400 ${padClass} font-normal"
208
+ >${title}</span
209
+ >`
210
+ : null}
211
+ ${repeat(items, item => item.slug, item => this.renderItem(item, padClass))}
212
+ `;
213
+ }
214
+ renderChips() {
215
+ return html `
216
+ <div
217
+ class="py-0.5 px-1.5 rounded-full bg-[#D71920] inline-flex"
218
+ style="background-color:#D71920;"
219
+ >
220
+ <span class="font-bold font-sans text-xs text-white capitalize"
221
+ >Baru</span
222
+ >
223
+ </div>
224
+ `;
225
+ }
240
226
  render() {
241
227
  return html `
242
- <!-- Button Menu -->
228
+ <!-- Toggle Button -->
243
229
  <div
230
+ role="button"
231
+ tabindex="0"
244
232
  class="w-fit flex items-center justify-center cursor-pointer relative"
245
233
  @click=${this.toggleNavSidebar}
234
+ @keydown=${(e) => {
235
+ if (e.key === 'Enter')
236
+ this.toggleNavSidebar(e);
237
+ }}
246
238
  >
247
239
  <slot></slot>
248
- ${!this.hasSlotContent
249
- ? html `
250
- <div
251
- class="h-4 inline-flex ${this.isDark
252
- ? 'text-[#FFFFFF]'
253
- : 'text-brand-1'}"
254
- >
255
- ${unsafeSVG(getFontAwesomeIcon('fas', 'bars'))}
256
- </div>
257
- <span
258
- class="font-sans hidden sm:inline ml-2 tracking-wide font-bold ${this
259
- .isDark
260
- ? 'text-[#FFFFFF]'
261
- : 'text-brand-1'}"
262
- >
263
- Menu
264
- </span>
265
- `
266
- : ''}
240
+ <div class="h-4 inline-flex text-brand-1">
241
+ ${unsafeSVG(getFontAwesomeIcon('fas', 'bars', 20, 20))}
242
+ </div>
243
+ <span
244
+ class="font-sans hidden sm:inline ml-2 tracking-wide font-bold text-brand-1"
245
+ >
246
+ Menu
247
+ </span>
267
248
  </div>
268
- <!-- Side Menu -->
249
+ <!-- Sidebar Menu -->
269
250
  <nav
270
- @click=${this.toggleNavSidebar}
271
251
  class=${this.showNavBar
272
252
  ? 'fixed left-0 top-0 w-screen z-[100]'
273
253
  : 'hidden'}
274
254
  >
255
+ <!-- Sidebar Content -->
275
256
  <div
276
- ref="toggle-nav-sidebar"
277
- class="bg-white h-screen menu-menu-sidebar overflow-y-auto pb-20 pt-0 shadow-lg"
278
- style="width: 312px;"
257
+ class="bg-white h-screen menu-menu-sidebar overflow-y-auto pb-20 shadow-lg"
258
+ style="width:312px;"
279
259
  >
260
+ <!-- Logo and Close Button -->
280
261
  <div
281
- class="bg-[#FFFFFF] flex flex-col items-center justify-center mb-6 w-full"
262
+ class="bg-[#FFFFFF] flex flex-col items-center justify-center w-full"
282
263
  >
283
264
  <div
284
265
  ref="logo-kompas"
@@ -293,267 +274,65 @@ let KompasMenuSideBar = class KompasMenuSideBar extends LitElement {
293
274
  />
294
275
  </a>
295
276
  <span
277
+ role="button"
278
+ tabindex="0"
296
279
  class="font-bold cursor-pointer text-grey-400 flex h-10 items-center justify-center rounded text-base w-10 py-4"
297
280
  @click=${this.toggleNavSidebar}
281
+ @keydown=${(e) => {
282
+ if (e.key === 'Enter')
283
+ this.toggleNavSidebar(e);
284
+ }}
298
285
  >
299
286
  ${unsafeSVG(getFontAwesomeIcon('fa', 'times', 20, 20))}
300
287
  </span>
301
288
  </div>
302
- <div class="flex flex-wrap px-6 w-full">
303
- ${this.dataExternal.map(item => html `
304
- <a href="${item.url}" class="flex w-1/2 no-underline">
305
- <div
306
- class="cursor-pointer flex items-center pb-4 w-[312px]"
307
- >
308
- ${item.icon &&
289
+ </div>
290
+ <!-- External Links -->
291
+ <div class="flex flex-wrap px-6">
292
+ ${repeat(this.dataExternal, item => item.name, item => html `
293
+ <a href="${item.url}" class="flex w-1/2 no-underline px-2">
294
+ <div class="cursor-pointer flex items-center pb-4">
295
+ ${item.icon &&
309
296
  Array.isArray(item.icon) &&
310
297
  item.icon.length >= 2
311
- ? html `
312
- <div class="flex mr-2 text-brand-1">
313
- ${unsafeSVG(getFontAwesomeIcon(item.icon[0], item.icon[1]))}
314
- </div>
315
- `
298
+ ? html `<div class="flex mr-2 text-brand-1">
299
+ ${unsafeSVG(getFontAwesomeIcon(item.icon[0], item.icon[1]))}
300
+ </div>`
316
301
  : ''}
317
- <span class="font-sans relative text-xs text-[#666666]">
318
- ${item.name}
319
- </span>
320
- <div class="ml-1">
321
- ${item.isNew ? this.renderChips() : ''}
322
- </div>
323
- </div>
324
- </a>
325
- `)}
326
- </div>
327
- </div>
328
- <div class="border-b border-[#DDD] m-6 "></div>
329
- <!-- feature -->
330
- <div class="flex">
331
- <div class="flex justify-between flex-col">
332
- ${this.dataSidebar.feature.map(item => html `
333
- <div class="w-full font-sans">
334
- <!-- Parent item -->
335
- <div
336
- class="flex items-center justify-between px-6 text-sm font-medium text-gray-700 transition-all cursor-pointer"
337
- @click=${(e) => this.rubricClicked(item, e)}
302
+ <span class="font-sans text-xs text-[#666666]"
303
+ >${item.name}</span
338
304
  >
339
- <div
340
- class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center"
341
- >
342
- <div class="flex items-center space-x-3">
343
- <span
344
- class="text-sm font-bold relative text-[#333] w-full"
345
- >${decodeSpecialChars(item.name)}</span
346
- >
347
- ${timedContent(item.redDot[0].start, item.redDot[0].end)
348
- ? html `<span
349
- class="bg-orange-400 h-2 relative rounded-full w-2 flex shrink-0 -top-[12px]"
350
- ></span>`
351
- : ''}
352
- </div>
353
- </div>
354
-
355
- <!-- Toggle chevron -->
356
- ${this.hasChildren(item)
357
- ? html `
358
- <span
359
- class="text-xs text-brand-1 bg-[#e1f0ff] flex justify-center items-center rounded my-1 p-4 w-10 h-10 cursor-pointer"
360
- @click=${(e) => {
361
- e.stopPropagation(); // Prevents click from bubbling to parent
362
- this.toggleChildren(item);
363
- }}
364
- >
365
- ${this.expandedSlug === item.slug
366
- ? unsafeSVG(getFontAwesomeIcon('fas', 'chevron-up', 12, 12))
367
- : unsafeSVG(getFontAwesomeIcon('fas', 'chevron-down', 12, 12))}
368
- </span>
369
- `
370
- : null}
371
- </div>
372
-
373
- <!-- Children items -->
374
- ${this.hasChildren(item) && this.expandedSlug === item.slug
375
- ? html `
376
- <div class="pl-14 pt-1 pb-2 space-y-1">
377
- ${item.children.map(child => html `
378
- <div
379
- class="flex items-center text-sm text-[#333] px-4 cursor-pointer transition-all"
380
- @click=${() => this.rubricClicked(child)}
381
- >
382
- <div
383
- class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center pl-11"
384
- >
385
- ${decodeSpecialChars(child.name)}
386
- ${timedContent(child.redDot[0].start, child.redDot[0].end)
387
- ? html `<span
388
- class="bg-orange-400 h-2 relative rounded-full w-2 flex shrink-0 -top-[12px]"
389
- ></span>`
390
- : ''}
391
- <div></div>
392
- </div>
393
- </div>
394
- `)}
395
- </div>
396
- `
305
+ ${item.isNew
306
+ ? html `<span class="ml-1">${this.renderChips()}</span>`
397
307
  : ''}
398
308
  </div>
399
- `)}
400
- </div>
309
+ </a>
310
+ `)}
401
311
  </div>
402
- <div class="border-b border-[#DDD] m-6 "></div>
403
- <!-- category -->
404
- <div class="flex">
405
- <div class="w-full flex justify-between flex-col">
406
- <span class="text-sm text-grey-400 px-6 font-normal"
407
- >Redaksional</span
408
- >
409
- ${this.dataSidebar.category.map(item => html `
410
- <div class="w-full font-sans">
411
- <!-- Parent item -->
412
- <div
413
- class="flex items-center justify-between text-sm font-medium px-6 transition-all cursor-pointer"
414
- @click=${(e) => this.rubricClicked(item, e)}
415
- >
416
- <div
417
- class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center"
418
- >
419
- <div class="flex items-center space-x-3">
420
- <span
421
- class="font-bold ${item.name === 'Beranda'
422
- ? 'text-[#00559a]'
423
- : 'text-[#333] w-full'}"
424
- >${decodeSpecialChars(item.name)}</span
425
- >
426
-
427
- ${timedContent(item.redDot[0].start, item.redDot[0].end)
428
- ? html `<span
429
- class="bg-orange-400 h-2 relative rounded-full w-2 flex shrink-0 -top-[12px]"
430
- ></span>`
431
- : ''}
432
- </div>
433
- </div>
434
-
435
- <!-- Toggle chevron -->
436
- ${this.hasChildren(item)
437
- ? html `
438
- <span
439
- class="flex justify-center items-center rounded my-1 py-4 w-10 h-10 cursor-pointer font-bold text-grey-400"
440
- @click=${(e) => {
441
- e.stopPropagation(); // Prevents click from bubbling to parent
442
- this.toggleChildren(item);
443
- }}
444
- >
445
- ${this.expandedSlug === item.slug
446
- ? unsafeSVG(getFontAwesomeIcon('fas', 'chevron-up', 12, 12))
447
- : unsafeSVG(getFontAwesomeIcon('fas', 'chevron-down', 12, 12))}
448
- </span>
449
- `
312
+ ${this.dataExternal.length > 0
313
+ ? html `<div class="border-b border-[#DDD] mx-6 my-4"></div>`
450
314
  : null}
451
- </div>
452
315
 
453
- <!-- Children items -->
454
- ${this.hasChildren(item) && this.expandedSlug === item.slug
455
- ? html `
456
- <div class="pt-1 pb-2 space-y-1">
457
- ${item.children.map(child => html `
458
- <div
459
- class="flex items-center text-sm text-[#333] px-4 cursor-pointer transition-all"
460
- @click=${() => this.rubricClicked(child)}
461
- >
462
- <div
463
- class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center pl-11"
464
- >
465
- ${decodeSpecialChars(child.name)}
466
- ${timedContent(child.redDot[0].start, child.redDot[0].end)
467
- ? html `<span
468
- class="bg-orange-400 h-2 relative rounded-full w-2 flex shrink-0 -top-[12px]"
469
- ></span>`
470
- : ''}
471
- </div>
472
- </div>
473
- `)}
474
- </div>
475
- `
476
- : ''}
477
- </div>
478
- `)}
479
- </div>
480
- </div>
316
+ <!-- Bundle Section -->
317
+ ${this.renderSection(null, this.dataSidebar.bundles, 'px-6')}
318
+ ${this.dataSidebar.bundles.length > 0
319
+ ? html `<div class="border-b border-[#DDD] mx-6 my-4"></div>`
320
+ : null}
481
321
 
482
- <div class="border-b border-[#DDD] m-6 "></div>
483
- <!-- Lainnya -->
484
- <div class="flex">
485
- <div class="w-full flex justify-between flex-col">
486
- <span class="text-sm text-grey-400 px-6 font-normal"
487
- >Lainnya</span
488
- >
489
- ${this.dataSidebar.lainnya.map(item => html `
490
- <div class="w-full font-sans">
491
- <!-- Parent item -->
492
- <div
493
- class="flex items-center justify-between text-sm font-medium px-6 transition-all cursor-pointer"
494
- @click=${(e) => this.rubricClicked(item, e)}
495
- >
496
- <div
497
- class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center"
498
- >
499
- <div class="flex items-center space-x-3">
500
- <span class="font-bold text-[#333]"
501
- >${decodeSpecialChars(item.name)}</span
502
- >
503
- ${timedContent(item.redDot[0].start, item.redDot[0].end)
504
- ? html `<span
505
- class="bg-orange-400 h-2 relative rounded-full w-2 flex shrink-0 -top-[12px]"
506
- ></span>`
507
- : ''}
508
- </div>
509
- </div>
322
+ <!-- Feature Section -->
323
+ ${this.renderSection(null, this.dataSidebar.feature, 'px-6')}
324
+ ${this.dataSidebar.feature.length > 0
325
+ ? html `<div class="border-b border-[#DDD] mx-6 my-4"></div>`
326
+ : null}
510
327
 
511
- <!-- Toggle chevron -->
512
- ${this.hasChildren(item)
513
- ? html `
514
- <span
515
- class="flex justify-center items-center rounded my-1 py-4 w-10 h-10 cursor-pointer font-bold"
516
- @click=${(e) => {
517
- e.stopPropagation(); // Prevents click from bubbling to parent
518
- this.toggleChildren(item);
519
- }}
520
- >
521
- ${this.expandedSlug === item.slug
522
- ? unsafeSVG(getFontAwesomeIcon('fas', 'chevron-up', 12, 12))
523
- : unsafeSVG(getFontAwesomeIcon('fas', 'chevron-down', 12, 12))}
524
- </span>
525
- `
328
+ <!-- Category (Redaksional) -->
329
+ ${this.renderSection('Redaksional', this.dataSidebar.category, 'px-6')}
330
+ ${this.dataSidebar.category.length > 0
331
+ ? html `<div class="border-b border-[#DDD] mx-6 my-4"></div>`
526
332
  : null}
527
- </div>
528
333
 
529
- <!-- Children items -->
530
- ${this.hasChildren(item) && this.expandedSlug === item.slug
531
- ? html `
532
- <div class="pt-1 pb-2 space-y-1">
533
- ${item.children.map(child => html `
534
- <div
535
- class="flex items-center text-sm text-[#333] px-4 cursor-pointer transition-all"
536
- @click=${() => this.rubricClicked(child)}
537
- >
538
- <div
539
- class="w-[216px] hover:bg-[#f3f4f6] rounded h-12 flex items-center pl-11"
540
- >
541
- ${decodeSpecialChars(child.name)}
542
- ${timedContent(child.redDot[0].start, child.redDot[0].end)
543
- ? html `<span
544
- class="bg-orange-400 h-2 relative rounded-full w-2 flex shrink-0 -top-[12px]"
545
- ></span>`
546
- : ''}
547
- </div>
548
- </div>
549
- `)}
550
- </div>
551
- `
552
- : ''}
553
- </div>
554
- `)}
555
- </div>
556
- </div>
334
+ <!-- Others (Lainnya) -->
335
+ ${this.renderSection('Lainnya', this.dataSidebar.lainnya, 'px-6')}
557
336
  </div>
558
337
  </nav>
559
338
  `;
@@ -580,35 +359,42 @@ KompasMenuSideBar.styles = [
580
359
  .menu-menu-sidebar::-webkit-scrollbar {
581
360
  width: 4px;
582
361
  }
583
-
584
362
  .menu-menu-sidebar::-webkit-scrollbar-track {
585
363
  background: white;
586
364
  }
587
-
588
365
  .menu-menu-sidebar::-webkit-scrollbar-thumb {
589
366
  background-color: #00557d; /* Replace with your brand color */
590
367
  border-radius: 8px;
591
368
  }
592
-
593
369
  .menu-menu-sidebar::-webkit-scrollbar-button,
594
370
  .menu-menu-sidebar::-webkit-scrollbar-corner {
595
371
  background-color: white;
596
372
  }
373
+ /* existing styles */
597
374
  `,
598
375
  TWStyles,
599
376
  ];
600
- __decorate([
601
- property({ type: Array })
602
- ], KompasMenuSideBar.prototype, "dataExternal", void 0);
603
377
  __decorate([
604
378
  property({ type: Boolean })
605
379
  ], KompasMenuSideBar.prototype, "isDark", void 0);
380
+ __decorate([
381
+ property({ type: Boolean })
382
+ ], KompasMenuSideBar.prototype, "isProductionMode", void 0);
383
+ __decorate([
384
+ property({ type: String })
385
+ ], KompasMenuSideBar.prototype, "subscriptionPackage", void 0);
606
386
  __decorate([
607
387
  state()
608
- ], KompasMenuSideBar.prototype, "expandedSlug", void 0);
388
+ ], KompasMenuSideBar.prototype, "dataExternal", void 0);
389
+ __decorate([
390
+ state()
391
+ ], KompasMenuSideBar.prototype, "dataSidebar", void 0);
609
392
  __decorate([
610
393
  state()
611
394
  ], KompasMenuSideBar.prototype, "showNavBar", void 0);
395
+ __decorate([
396
+ state()
397
+ ], KompasMenuSideBar.prototype, "expandedSlug", void 0);
612
398
  KompasMenuSideBar = __decorate([
613
399
  customElement('kompasid-menu-side-bar')
614
400
  ], KompasMenuSideBar);