mertani-web-toolkit 0.1.64 → 0.1.66

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.
@@ -59,35 +59,56 @@
59
59
  box-shadow 0.2s;
60
60
  }
61
61
 
62
- .select-trigger:not(:disabled) {
62
+ .select-trigger:not(.disabled) {
63
63
  background: var(--color-bg-surface);
64
64
  cursor: pointer;
65
65
  }
66
66
 
67
- .select-trigger:not(:disabled):hover {
67
+ .select-trigger:not(.disabled):hover {
68
68
  border-color: var(--color-border-form);
69
69
  }
70
70
 
71
- .select-trigger:not(:disabled):focus {
71
+ .select-trigger:not(.disabled):focus {
72
72
  outline: none;
73
73
  border-color: var(--color-bg-act-primary);
74
74
  box-shadow: 0 0 0 2px var(--color-bg-act-primary) 40;
75
75
  }
76
76
 
77
- .select-trigger:disabled {
77
+ .select-trigger.disabled {
78
78
  cursor: not-allowed;
79
79
  background: var(--color-bg-disabled);
80
80
  }
81
81
 
82
- .select-trigger.error:not(:disabled) {
82
+ .select-trigger.error:not(.disabled) {
83
83
  border-color: var(--color-text-error-ti);
84
84
  }
85
85
 
86
- .select-trigger.error:not(:disabled):focus {
86
+ .select-trigger.error:not(.disabled):focus {
87
87
  border-color: var(--color-text-error-ti);
88
88
  box-shadow: 0 0 0 2px var(--color-text-error-ti) 40;
89
89
  }
90
90
 
91
+ .select-clear-button {
92
+ display: flex;
93
+ align-items: center;
94
+ justify-content: center;
95
+ padding: 4px;
96
+ border-radius: 4px;
97
+ color: var(--color-text-tertiary);
98
+ background: transparent;
99
+ border: none;
100
+ cursor: pointer;
101
+ transition:
102
+ color 0.2s,
103
+ background-color 0.2s;
104
+ line-height: 0;
105
+ }
106
+
107
+ .select-clear-button:hover {
108
+ color: var(--color-text-primary);
109
+ background: var(--color-bg-disabled);
110
+ }
111
+
91
112
  .select-menu {
92
113
  position: absolute;
93
114
  right: 0;
@@ -41,6 +41,7 @@
41
41
  onOpen?: () => void;
42
42
  /** Dipanggil saat teks search berubah (debounce 300ms), hanya jika remoteSearch. */
43
43
  onSearchQueryChange?: (query: string) => void;
44
+ onClear?: () => void;
44
45
 
45
46
  // Validation
46
47
  isMandatory?: boolean;
@@ -56,6 +57,7 @@
56
57
  class?: string;
57
58
  style?: string;
58
59
  isShowChevron?: boolean;
60
+ isClearable?: boolean;
59
61
  }
60
62
 
61
63
  const {
@@ -92,6 +94,7 @@
92
94
  onSelect,
93
95
  onOpen,
94
96
  onSearchQueryChange,
97
+ onClear,
95
98
 
96
99
  // Validation
97
100
  isMandatory = false,
@@ -105,7 +108,8 @@
105
108
 
106
109
  class: className = '',
107
110
  style: customStyle = '',
108
- isShowChevron = true
111
+ isShowChevron = true,
112
+ isClearable = false
109
113
  }: Props = $props();
110
114
 
111
115
  // ===== Constants =====
@@ -123,7 +127,7 @@
123
127
  let open = $state(false);
124
128
  let search = $state('');
125
129
  let placement: 'bottom' | 'top' = $state('bottom');
126
- let triggerEl: HTMLButtonElement | null = $state(null);
130
+ let triggerEl: HTMLDivElement | null = $state(null);
127
131
  let menuEl: HTMLDivElement | null = $state(null);
128
132
  let resizeObs: ResizeObserver | null = $state(null);
129
133
  let unregisterDropdown: (() => void) | null = $state(null);
@@ -306,6 +310,13 @@
306
310
  close();
307
311
  }
308
312
 
313
+ function handleClear(e: MouseEvent) {
314
+ e.stopPropagation();
315
+ onSelect?.('');
316
+ onClear?.();
317
+ error = validateInput('');
318
+ }
319
+
309
320
  function validateInput(val: string): string {
310
321
  if (customValidation) {
311
322
  const customError = customValidation(val);
@@ -403,28 +414,42 @@
403
414
  </label>
404
415
  {/if}
405
416
  <div class="relative flex-1">
406
- <button
417
+ <div
407
418
  bind:this={triggerEl}
408
- type="button"
409
- class="select-trigger {className} {error ? 'error' : ''}"
410
- style={triggerStyles()}
419
+ role="combobox"
420
+ tabindex="0"
411
421
  aria-haspopup="listbox"
412
422
  aria-expanded={open}
423
+ aria-controls={open ? 'select-menu' : undefined}
424
+ class="select-trigger {className} {error ? 'error' : ''}"
425
+ style={triggerStyles()}
413
426
  onclick={toggle}
414
427
  onkeydown={handleKeydown}
415
428
  onfocus={handleFocus}
416
429
  onblur={handleBlur}
417
- disabled={disabled || isLoading}
418
430
  title={tooltip || ''}
431
+ class:disabled={disabled || isLoading}
419
432
  >
420
433
  <span class="truncate">{labelOf(value) || placeholder}</span>
421
- {#if isShowChevron}
422
- <Icon
423
- name="bs-chevron-down"
424
- style="transform-origin: center; transition: transform 0.25s; transform: rotate({chevronRotation});"
425
- />
426
- {/if}
427
- </button>
434
+ <div class="flex items-center gap-1">
435
+ {#if isClearable && value && !disabled && !isLoading}
436
+ <button
437
+ type="button"
438
+ class="select-clear-button"
439
+ onclick={handleClear}
440
+ aria-label="Clear selection"
441
+ >
442
+ <Icon name="bs-x-lg" />
443
+ </button>
444
+ {/if}
445
+ {#if isShowChevron}
446
+ <Icon
447
+ name="bs-chevron-down"
448
+ style="transform-origin: center; transition: transform 0.25s; transform: rotate({chevronRotation});"
449
+ />
450
+ {/if}
451
+ </div>
452
+ </div>
428
453
 
429
454
  {#if open}
430
455
  <div
@@ -28,6 +28,7 @@ interface Props {
28
28
  onOpen?: () => void;
29
29
  /** Dipanggil saat teks search berubah (debounce 300ms), hanya jika remoteSearch. */
30
30
  onSearchQueryChange?: (query: string) => void;
31
+ onClear?: () => void;
31
32
  isMandatory?: boolean;
32
33
  customValidation?: (value: string) => string | null;
33
34
  isLoading?: boolean;
@@ -37,6 +38,7 @@ interface Props {
37
38
  class?: string;
38
39
  style?: string;
39
40
  isShowChevron?: boolean;
41
+ isClearable?: boolean;
40
42
  }
41
43
  declare const SelectInput: import("svelte").Component<Props, {}, "">;
42
44
  type SelectInput = ReturnType<typeof SelectInput>;
package/dist/index.d.ts CHANGED
@@ -10,7 +10,6 @@ export { default as Radio } from './components/inputs/Radio/Radio.svelte';
10
10
  export { default as Toggle } from './components/inputs/Toggle/Toggle.svelte';
11
11
  export { default as Segmented } from './components/inputs/Segmented/Segmented.svelte';
12
12
  export { default as Steppers } from './components/inputs/Steppers/Steppers.svelte';
13
- export { default as IMSLayout1 } from './layouts/IMS/IMSLayout1/IMSLayout1.svelte';
14
13
  export { default as Table } from './components/Table/Table.svelte';
15
14
  export { default as HeaderContent } from './components/HeaderContent/HeaderContent.svelte';
16
15
  export { default as TableBadge } from './components/Table/TableBadge.svelte';
package/dist/index.js CHANGED
@@ -10,7 +10,6 @@ export { default as Radio } from './components/inputs/Radio/Radio.svelte';
10
10
  export { default as Toggle } from './components/inputs/Toggle/Toggle.svelte';
11
11
  export { default as Segmented } from './components/inputs/Segmented/Segmented.svelte';
12
12
  export { default as Steppers } from './components/inputs/Steppers/Steppers.svelte';
13
- export { default as IMSLayout1 } from './layouts/IMS/IMSLayout1/IMSLayout1.svelte';
14
13
  export { default as Table } from './components/Table/Table.svelte';
15
14
  export { default as HeaderContent } from './components/HeaderContent/HeaderContent.svelte';
16
15
  export { default as TableBadge } from './components/Table/TableBadge.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mertani-web-toolkit",
3
- "version": "0.1.64",
3
+ "version": "0.1.66",
4
4
  "homepage": "https://storybook.mertani.com/",
5
5
  "scripts": {
6
6
  "dev": "vite dev",
@@ -1,3 +0,0 @@
1
- @import 'tailwindcss';
2
- @import 'tailwindcss/theme';
3
- @import 'tailwindcss/utilities';
@@ -1,38 +0,0 @@
1
- <script lang="ts">
2
- import './IMSLayout1.css';
3
- import ImsHeader from './components/ImsHeader.svelte';
4
- import ImsSidebar from './components/ImsSidebar.svelte';
5
- import type { IImsLayout } from './types/IImsLayout.js';
6
-
7
- const { children, cmsNamespaceResponseData, header, sidebar, pageInfo, content }: IImsLayout = $props();
8
-
9
- let showSidebar = $state(true);
10
-
11
- function onToggleSidebar() {
12
- showSidebar = !showSidebar;
13
- }
14
- </script>
15
-
16
- <svelte:head>
17
- <title>{cmsNamespaceResponseData.name}</title>
18
- </svelte:head>
19
-
20
- <div class="flex h-screen flex-col bg-[#F5F5F5]">
21
- <ImsHeader {sidebar} version={header?.version} {content} />
22
- <div class="flex flex-1 overflow-hidden">
23
- <ImsSidebar
24
- {showSidebar}
25
- {onToggleSidebar}
26
- bind:show={showSidebar}
27
- {pageInfo}
28
- {sidebar}
29
- namespaces={cmsNamespaceResponseData.namespaces}
30
- />
31
- <main class="flex-1 overflow-auto bg-[#f6f8fa]">
32
- {@render children?.()}
33
- </main>
34
- </div>
35
- </div>
36
-
37
- <style>
38
- </style>
@@ -1,5 +0,0 @@
1
- import './IMSLayout1.css';
2
- import type { IImsLayout } from './types/IImsLayout.js';
3
- declare const IMSLayout1: import("svelte").Component<IImsLayout, {}, "">;
4
- type IMSLayout1 = ReturnType<typeof IMSLayout1>;
5
- export default IMSLayout1;
@@ -1,20 +0,0 @@
1
- <script lang="ts">
2
- import type { Snippet } from 'svelte';
3
- import type { ISidebarData } from '../types/IImsLayout.js';
4
-
5
- const {
6
- version = 'v1.0.0',
7
- sidebar,
8
- content
9
- } = $props<{ version?: string; sidebar: ISidebarData; content?: Snippet }>();
10
- </script>
11
-
12
- <header
13
- class="sticky top-0 z-20 flex h-15 items-center justify-between border-b border-[#e0e0e0] bg-white p-4"
14
- >
15
- <div class="flex h-15 items-center gap-2 border-b border-[#EAECF0]">
16
- <img src={sidebar.logoUrl} alt={'Logo'} class="h-13 object-contain" />
17
- {@html content}
18
- </div>
19
- <span class="text-sm font-medium">Versi {version}</span>
20
- </header>
@@ -1,10 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- import type { ISidebarData } from '../types/IImsLayout.js';
3
- type $$ComponentProps = {
4
- version?: string;
5
- sidebar: ISidebarData;
6
- content?: Snippet;
7
- };
8
- declare const ImsHeader: import("svelte").Component<$$ComponentProps, {}, "">;
9
- type ImsHeader = ReturnType<typeof ImsHeader>;
10
- export default ImsHeader;
@@ -1,469 +0,0 @@
1
- <script lang="ts">
2
- import { onMount } from 'svelte';
3
- import { goto } from '$app/navigation';
4
- import { page } from '$app/state';
5
- import ChevronDown from '../../../../icons/ChevronDown.svelte';
6
- import GearTwo from '../../../../icons/GearTwo.svelte';
7
- import User from '../../../../icons/User.svelte';
8
- import Logout from '../../../../icons/Logout.svelte';
9
- import type { ISidebarData, ISidebarNamespace } from '../types/IImsLayout.js';
10
- import { USER_ROLE_ADMIN, UserStore } from '../../../../stores/UserStore.js';
11
- import { deleteCookie, USER_TOKEN } from '../../../../utils/Cookie.js';
12
- import Window from '../../../../icons/Window.svelte';
13
- import Icon from '../../../../components/Icon/Icon.svelte';
14
-
15
- const {
16
- show = $bindable(true),
17
- pageInfo,
18
- sidebar,
19
- namespaces,
20
- showSidebar,
21
- onToggleSidebar
22
- } = $props<{
23
- show?: boolean;
24
- pageInfo: { namespace: string };
25
- sidebar: ISidebarData;
26
- namespaces: ISidebarNamespace[];
27
- showSidebar: boolean;
28
- onToggleSidebar: () => void;
29
- }>();
30
-
31
- let selectedDropdownId = $state(pageInfo.namespace || namespaces?.[0]?.id);
32
- let areaDropdownOpen = $state(false);
33
- let userMenuOpen = $state(false);
34
- let openGroups = $state<Record<string, boolean>>({});
35
-
36
- let dropdownRef: HTMLDivElement | undefined;
37
- const user = sidebar.user ?? { name: '', role: '', initials: '' };
38
- const isAdmin = user?.role === USER_ROLE_ADMIN;
39
-
40
- const navItems = $derived(sidebar.nav ?? []);
41
- const selectedDropdownLabel = $derived(
42
- namespaces?.find((item: any) => item.id === selectedDropdownId)?.name ?? ''
43
- );
44
-
45
- onMount(() => {
46
- const handleDocumentClick = (event: MouseEvent) => {
47
- if (!dropdownRef) return;
48
- const target = event.target as Node | null;
49
- if (!target || dropdownRef.contains(target)) return;
50
- areaDropdownOpen = false;
51
- };
52
-
53
- document.addEventListener('click', handleDocumentClick);
54
- return () => document.removeEventListener('click', handleDocumentClick);
55
- });
56
-
57
- function toggleAreaDropdown() {
58
- areaDropdownOpen = !areaDropdownOpen;
59
- }
60
-
61
- function closeAreaDropdown() {
62
- areaDropdownOpen = false;
63
- }
64
-
65
- function toggleUserMenu() {
66
- userMenuOpen = !userMenuOpen;
67
- }
68
-
69
- function handleLogout() {
70
- toggleUserMenu();
71
- UserStore.set(null);
72
- deleteCookie(USER_TOKEN);
73
- sessionStorage.removeItem('organization_detail');
74
- goto('/');
75
- }
76
-
77
- function handleProfileClick() {
78
- goto('/user/profile');
79
- }
80
-
81
- function selectArea(areaId: string) {
82
- selectedDropdownId = areaId;
83
- closeAreaDropdown();
84
-
85
- // Split the current pathname and find if any segment matches an area id
86
- const pathSegments = page.url.pathname.split('/').filter(Boolean);
87
- const areaIndex = pathSegments.findIndex((segment) =>
88
- namespaces?.some((item: any) => item.id === segment)
89
- );
90
-
91
- if (areaIndex !== -1) {
92
- // Replace the matched area id with the newly selected areaId
93
- pathSegments[areaIndex] = areaId;
94
- const newPath = '/' + pathSegments.join('/');
95
- goto(newPath);
96
- }
97
- }
98
-
99
- function gotoSlug(slug: string) {
100
- if (!slug) return;
101
- const segments = page.url.pathname.split('/').filter(Boolean);
102
- const areaIndex = segments.findIndex((segment) =>
103
- namespaces?.some((item: any) => item.id === segment)
104
- );
105
- const baseSegments = areaIndex !== -1 ? segments.slice(0, areaIndex + 1) : segments;
106
- const targetPath = '/' + [...baseSegments, slug].join('/');
107
- if (targetPath !== page.url.pathname) {
108
- goto(targetPath);
109
- }
110
- }
111
-
112
- function handleAreaButtonKeydown(event: KeyboardEvent) {
113
- if (event.key === 'Enter' || event.key === ' ' || event.key === 'ArrowDown') {
114
- event.preventDefault();
115
- if (!areaDropdownOpen) {
116
- areaDropdownOpen = true;
117
- }
118
- }
119
- if (event.key === 'Escape') {
120
- event.preventDefault();
121
- closeAreaDropdown();
122
- }
123
- }
124
-
125
- function toggleGroup(title: string) {
126
- openGroups = { ...openGroups, [title]: !openGroups[title] };
127
- }
128
-
129
- $effect(() => {
130
- if (typeof window === 'undefined') {
131
- return;
132
- }
133
-
134
- const pathname = page.url.pathname;
135
- const items = navItems;
136
- if (!items.length) {
137
- return;
138
- }
139
-
140
- const hasMatch = items.some((item: any) => {
141
- if (item.children && item.children.length) {
142
- return item.children.some((child: any) => pathname.split('/').includes(child.slug));
143
- }
144
- return pathname.split('/').includes(item.slug);
145
- });
146
- if (hasMatch) {
147
- return;
148
- }
149
-
150
- const fallbackItem = items[0];
151
- const targetSlug = fallbackItem.children?.[0]?.slug ?? fallbackItem.slug;
152
-
153
- //TODO: buat dinamis untuk White list path
154
- const pathSegments = pathname.split('/');
155
- if (pathSegments.includes('kelola-sub-daerah-irigasi')) {
156
- if (sidebar?.user?.role === USER_ROLE_ADMIN) {
157
- return;
158
- } else {
159
- goto('/404');
160
- return;
161
- }
162
- }
163
- if (targetSlug && !pathSegments.includes(targetSlug)) {
164
- gotoSlug(targetSlug);
165
- }
166
- });
167
-
168
- $effect(() => {
169
- if (!show) {
170
- areaDropdownOpen = false;
171
- userMenuOpen = false;
172
- }
173
- });
174
- </script>
175
-
176
- <aside
177
- class={`relative shrink-0 overflow-visible border-r border-[#e0e0e0] bg-white transition-all duration-200 ease-in-out ${
178
- show ? 'w-[250px]' : 'w-14'
179
- }`}
180
- >
181
- <button
182
- type="button"
183
- title="Toggle sidebar"
184
- onclick={onToggleSidebar}
185
- class={`absolute top-1 right-2 flex h-10 w-10 items-center justify-center rounded-lg border border-transparent bg-[#fff] text-[#495057] transition hover:border-[#e0e0e0] hover:bg-[#f5f5f5]`}
186
- >
187
- <div class={`transition-transform duration-300 ${show ? '' : 'rotate-180'}`}>
188
- <Icon name="window" width={16} height={16} />
189
- </div>
190
- </button>
191
-
192
- {#if show}
193
- <div class={`flex h-full flex-col bg-white pt-6 ${show ? '' : 'hidden'}`}>
194
- <div class="flex flex-col gap-1 border-b border-[#EAECF0] px-4 py-4" bind:this={dropdownRef}>
195
- <div class="text-sm font-medium text-[#2C2C30]">
196
- {sidebar.dropdownLabel || 'Pilih Sub Daerah Irigasi'}
197
- </div>
198
- <div class="flex items-center rounded-sm border border-[#CED4DA]">
199
- {#if show}
200
- <div class="relative flex-1">
201
- <button
202
- type="button"
203
- class="flex w-full items-center justify-between rounded-sm bg-white p-2 text-left text-sm text-[#2C2C30]"
204
- onclick={toggleAreaDropdown}
205
- onkeydown={handleAreaButtonKeydown}
206
- >
207
- <span class="block w-32 overflow-hidden text-ellipsis whitespace-nowrap"
208
- >{selectedDropdownLabel || 'Pilih'}</span
209
- >
210
- <ChevronDown direction={areaDropdownOpen ? 'up' : 'down'} />
211
- </button>
212
- {#if areaDropdownOpen}
213
- <div
214
- class="absolute top-full right-0 left-0 z-20 mt-2 overflow-hidden rounded-md bg-white shadow-lg"
215
- >
216
- <div class="max-h-56 overflow-y-auto py-1">
217
- {#if namespaces.length}
218
- {#each namespaces as area}
219
- <button
220
- type="button"
221
- class={`flex w-full items-center justify-between gap-2 px-3 py-2 text-left text-xs transition ${
222
- area.id === selectedDropdownId
223
- ? 'text-[#F79B09]'
224
- : 'text-[#212529] hover:bg-[#F5F5F5]'
225
- }`}
226
- onclick={() => selectArea(area.id)}
227
- >
228
- <span class="truncate">{area.name}</span>
229
- </button>
230
- {/each}
231
- {:else}
232
- <div class="px-3 py-2 text-xs text-slate-400">Tidak ada hasil</div>
233
- {/if}
234
- </div>
235
- </div>
236
- {/if}
237
- </div>
238
- {/if}
239
- {#if isAdmin}
240
- <button
241
- type="button"
242
- onclick={() => gotoSlug('kelola-sub-daerah-irigasi')}
243
- class="flex size-9 items-center justify-center rounded-r-sm border-l border-[#CED4DA] bg-[#E9ECEF] text-[#2C2C30]"
244
- >
245
- <GearTwo />
246
- </button>
247
- {/if}
248
- </div>
249
- </div>
250
-
251
- <nav class="flex flex-1 flex-col gap-2 overflow-y-auto p-4">
252
- {#each sidebar.nav as item}
253
- <div>
254
- {#if item.children?.length}
255
- <button
256
- type="button"
257
- class="flex w-full items-center justify-between gap-2 rounded-md px-2.5 py-2 text-left text-[14px] text-[#2C2C30] transition hover:bg-[#F5F5F5]"
258
- onclick={() => toggleGroup(item.title)}
259
- >
260
- <span class="flex items-center gap-2">
261
- {#if item.icon}
262
- <span class="text-[#495057]">{@html item.icon}</span>
263
- {/if}
264
- <span>{item.title}</span>
265
- </span>
266
- <ChevronDown direction={openGroups[item.title] ? 'up' : 'down'} />
267
- </button>
268
- {#if openGroups[item.title]}
269
- <div class="mt-1 ml-6 flex flex-col gap-1">
270
- {#each item.children as child}
271
- <button
272
- onclick={() => gotoSlug(child.slug)}
273
- class={`flex items-center gap-2 rounded-md px-2.5 py-2 text-[14px] text-[#2C2C30] transition hover:bg-[#F5F5F5] ${page.url.pathname.split('/').includes(child.slug) ? 'bg-[#F8F9FA] text-[#F79B09]' : ''}`}
274
- >
275
- {#if child.icon}
276
- <span class="text-[#495057]">{@html child.icon}</span>
277
- {/if}
278
- <span class="text-left">{child.title}</span>
279
- </button>
280
- {/each}
281
- </div>
282
- {/if}
283
- {:else}
284
- <button
285
- onclick={() => gotoSlug(item.slug)}
286
- class={`flex w-full items-center justify-between gap-2 rounded-md px-2.5 py-2 text-[14px] text-[#2C2C30] transition hover:bg-[#F5F5F5] ${page.url.pathname.split('/').includes(item.slug) ? 'bg-[#F8F9FA] text-[#F79B09]' : ''}`}
287
- >
288
- <span class="flex items-center gap-2">
289
- {#if item.icon}
290
- <span class="text-[#495057]">{@html item.icon}</span>
291
- {/if}
292
- <span>{item.title}</span>
293
- </span>
294
- </button>
295
- {/if}
296
- </div>
297
- {/each}
298
- </nav>
299
-
300
- <div class="relative border-t border-[#EAECF0] p-4">
301
- <button
302
- type="button"
303
- class="flex w-full items-center gap-2 text-left"
304
- onclick={toggleUserMenu}
305
- >
306
- <div class="grid size-9 place-items-center">
307
- <img src={user.avatarUrl} alt="avatar" class="size-full rounded-full object-cover" />
308
- </div>
309
- <div class="min-w-0 flex-1">
310
- <div class="truncate text-[12px] font-medium text-[#495057]">{user.name}</div>
311
- <div class="truncate text-[10px] text-[#ADB5BD]">{user.role}</div>
312
- </div>
313
- <ChevronDown direction={'right'} />
314
- </button>
315
- {#if userMenuOpen}
316
- <div
317
- class="absolute bottom-0 left-[calc(100%+12px)] z-30 w-[216px] rounded-xl border border-[#EAECF0] bg-white p-4 text-left shadow-[0px_12px_32px_rgba(15,23,42,0.12)]"
318
- >
319
- <div class="flex flex-col gap-3">
320
- <!-- <div>
321
- <div class="text-xs font-semibold text-[#2C2C30]">Ubah Role</div>
322
- <div class="mt-2">
323
- <select
324
- class="w-full rounded-md border border-[#CED4DA] bg-white px-3 py-2 text-xs text-[#2C2C30] focus:outline-none focus:ring-2 focus:ring-[#F79B09]/40"
325
- >
326
- </select>
327
- </div>
328
- <div class="mt-1 text-[10px] text-[#ADB5BD]">Lihat view dari role lainnya</div>
329
- </div>
330
-
331
- <hr class="border-[#EAECF0]" /> -->
332
-
333
- <button
334
- type="button"
335
- class="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-xs font-medium text-[#2C2C30] transition hover:bg-[#F5F5F5]"
336
- onclick={handleProfileClick}
337
- >
338
- <User />
339
- <span>Profil Akun</span>
340
- </button>
341
-
342
- <button
343
- type="button"
344
- class="flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-xs font-semibold text-[#D14343] transition hover:bg-[#FFF5F0]"
345
- onclick={handleLogout}
346
- >
347
- <span>Keluar / Log Out</span>
348
- <span class="flex items-center gap-1 text-[#D14343]">
349
- <Logout />
350
- </span>
351
- </button>
352
- </div>
353
- </div>
354
- {/if}
355
- </div>
356
- </div>
357
- {:else}
358
- <div class="flex h-full flex-col items-center pt-6">
359
- <div class="mb-3 h-8 w-8 rounded-sm bg-transparent"></div>
360
-
361
- <nav class="w-full flex-1 overflow-hidden overflow-y-auto px-2">
362
- {#each sidebar.nav as item}
363
- {#if item.children?.length}
364
- <!-- Group root icon with fly-out -->
365
- <div class="group relative my-1">
366
- <button
367
- type="button"
368
- onclick={onToggleSidebar}
369
- class="mx-auto flex h-10 w-10 items-center justify-center rounded-md text-[#2C2C30] hover:bg-[#F5F5F5]"
370
- aria-haspopup="true"
371
- aria-expanded={openGroups[item.title] ? 'true' : 'false'}
372
- title={item.title}
373
- onmouseenter={() => (openGroups = { ...openGroups, [item.title]: true })}
374
- onmouseleave={() => (openGroups = { ...openGroups, [item.title]: false })}
375
- >
376
- {#if item.icon}
377
- <span class="text-[#495057]">{@html item.icon}</span>
378
- {/if}
379
- </button>
380
-
381
- {#if openGroups[item.title]}
382
- <!-- svelte-ignore a11y_no_static_element_interactions -->
383
- <div
384
- class="absolute top-0 left-[3.25rem] z-30 w-48 overflow-hidden rounded-md border border-[#EAECF0] bg-white py-1 shadow-lg"
385
- onmouseenter={() => (openGroups = { ...openGroups, [item.title]: true })}
386
- onmouseleave={() => (openGroups = { ...openGroups, [item.title]: false })}
387
- >
388
- {#each item.children as child}
389
- <button
390
- onclick={() => gotoSlug(child.slug)}
391
- class={`flex w-full items-center gap-2 px-3 py-2 text-sm transition hover:bg-[#F5F5F5] ${
392
- page.url.pathname.split('/').includes(child.slug)
393
- ? 'bg-[#F8F9FA] text-[#F79B09]'
394
- : 'text-[#2C2C30]'
395
- }`}
396
- title={child.title}
397
- >
398
- {#if child.icon}
399
- <span class="text-[#495057]">{@html item.icon}</span>
400
- {/if}
401
- <span class="truncate">{child.title}</span>
402
- </button>
403
- {/each}
404
- </div>
405
- {/if}
406
- </div>
407
- {:else}
408
- <!-- Single item icon -->
409
- <button
410
- onclick={() => gotoSlug(item.slug)}
411
- class={`mx-auto my-1 flex h-10 w-10 items-center justify-center rounded-md transition hover:bg-[#F5F5F5] ${
412
- page.url.pathname.split('/').includes(item.slug)
413
- ? 'bg-[#F8F9FA] ring-1 ring-[#F79B09]/40'
414
- : ''
415
- }`}
416
- title={item.title}
417
- aria-label={item.title}
418
- >
419
- {#if item.icon}
420
- <span class="text-[#495057]">{@html item.icon}</span>
421
- {/if}
422
- </button>
423
- {/if}
424
- {/each}
425
- </nav>
426
-
427
- <!-- User avatar + quick menu (icon only) -->
428
- <div class="relative flex w-full items-center justify-center border-t border-[#EAECF0] p-3">
429
- <button
430
- type="button"
431
- class="grid size-9 place-items-center rounded-full"
432
- onclick={toggleUserMenu}
433
- title={`${user.name} • ${user.role}`}
434
- aria-haspopup="true"
435
- aria-expanded={userMenuOpen ? 'true' : 'false'}
436
- >
437
- <img src={user.avatarUrl} alt="avatar" class="size-full rounded-full object-cover" />
438
- </button>
439
-
440
- {#if userMenuOpen}
441
- <div
442
- class="absolute bottom-3 left-[3.25rem] z-30 w-56 rounded-xl border border-[#EAECF0] bg-white p-4 text-left shadow-[0px_12px_32px_rgba(15,23,42,0.12)]"
443
- >
444
- <div class="mb-2">
445
- <div class="truncate text-xs font-medium text-[#495057]">{user.name}</div>
446
- <div class="truncate text-[10px] text-[#ADB5BD]">{user.role}</div>
447
- </div>
448
- <button
449
- type="button"
450
- class="flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-xs font-medium text-[#2C2C30] transition hover:bg-[#F5F5F5]"
451
- onclick={handleProfileClick}
452
- >
453
- <User />
454
- <span>Profil Akun</span>
455
- </button>
456
- <button
457
- type="button"
458
- class="mt-1 flex w-full items-center justify-between gap-2 rounded-md px-2 py-1.5 text-xs font-semibold text-[#D14343] transition hover:bg-[#FFF5F0]"
459
- onclick={handleLogout}
460
- >
461
- <span>Keluar / Log Out</span>
462
- <span class="flex items-center gap-1 text-[#D14343]"><Logout /></span>
463
- </button>
464
- </div>
465
- {/if}
466
- </div>
467
- </div>
468
- {/if}
469
- </aside>
@@ -1,14 +0,0 @@
1
- import type { ISidebarData, ISidebarNamespace } from '../types/IImsLayout.js';
2
- type $$ComponentProps = {
3
- show?: boolean;
4
- pageInfo: {
5
- namespace: string;
6
- };
7
- sidebar: ISidebarData;
8
- namespaces: ISidebarNamespace[];
9
- showSidebar: boolean;
10
- onToggleSidebar: () => void;
11
- };
12
- declare const ImsSidebar: import("svelte").Component<$$ComponentProps, {}, "show">;
13
- type ImsSidebar = ReturnType<typeof ImsSidebar>;
14
- export default ImsSidebar;
@@ -1,55 +0,0 @@
1
- import type { Snippet } from 'svelte';
2
- export interface IImsLayoutHeader {
3
- version: string;
4
- }
5
- export interface ISidebarNamespace {
6
- id: string;
7
- name: string;
8
- }
9
- export interface ISidebarNavChild {
10
- title: string;
11
- slug: string;
12
- icon?: string;
13
- }
14
- export interface ISidebarNavItem {
15
- title: string;
16
- slug?: string;
17
- icon?: string;
18
- children?: ISidebarNavChild[];
19
- }
20
- export interface ISidebarUser {
21
- name: string;
22
- role: string;
23
- avatarUrl?: string;
24
- roleOptions?: Array<unknown>;
25
- }
26
- export interface ISidebarData {
27
- logoUrl: string;
28
- dropdownLabel?: string;
29
- nav: ISidebarNavItem[];
30
- user: ISidebarUser;
31
- }
32
- export interface CMSNamespaceItem {
33
- id: string;
34
- name: string;
35
- }
36
- export interface CMSNamespaceResponse {
37
- cms_type: string;
38
- enable_public_page: boolean;
39
- id: string;
40
- name: string;
41
- namespaces: CMSNamespaceItem[];
42
- slug: string;
43
- base_url: string;
44
- }
45
- export interface IImsLayout {
46
- cmsNamespaceResponseData: CMSNamespaceResponse;
47
- type: string;
48
- header: IImsLayoutHeader;
49
- sidebar: ISidebarData;
50
- children: Snippet;
51
- content?: Snippet;
52
- pageInfo: {
53
- namespace: string;
54
- };
55
- }
@@ -1 +0,0 @@
1
- export {};
@@ -1,44 +0,0 @@
1
- export declare const IImsLayout: {
2
- type: string;
3
- cmsNamespaceResponseData: {
4
- id: string;
5
- slug: string;
6
- name: string;
7
- cms_type: string;
8
- base_url: string;
9
- enable_public_page: boolean;
10
- namespaces: {
11
- id: string;
12
- name: string;
13
- }[];
14
- };
15
- pageInfo: {
16
- namespace: string;
17
- };
18
- header: {
19
- version: string;
20
- };
21
- sidebar: {
22
- logoUrl: string;
23
- nav: ({
24
- icon: string;
25
- slug: string;
26
- title: string;
27
- children?: undefined;
28
- } | {
29
- children: {
30
- icon: string;
31
- slug: string;
32
- title: string;
33
- }[];
34
- icon: string;
35
- title: string;
36
- slug?: undefined;
37
- })[];
38
- user: {
39
- avatarUrl: string;
40
- name: string;
41
- role: string;
42
- };
43
- };
44
- };
@@ -1,88 +0,0 @@
1
- export const IImsLayout = {
2
- type: 'ims-layout1',
3
- cmsNamespaceResponseData: {
4
- id: '',
5
- slug: 'ims-saddang',
6
- name: 'Saddang',
7
- cms_type: 'IMS',
8
- base_url: 'https://cms.mertani.my.id',
9
- enable_public_page: true,
10
- namespaces: [
11
- {
12
- id: '1efbafdf-f83f-42ba-a710-29f875598895',
13
- name: 'pekkaabata'
14
- },
15
- {
16
- id: '5fa1932e-dbca-442d-b06b-a675c5f390bd',
17
- name: 'Saddang'
18
- }
19
- ]
20
- },
21
- pageInfo: {
22
- namespace: '5fa1932e-dbca-442d-b06b-a675c5f390bd'
23
- },
24
- header: {
25
- version: '1.2.0'
26
- },
27
- sidebar: {
28
- logoUrl: '/assets/images/logo.png',
29
- nav: [
30
- {
31
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
32
- slug: 'beranda',
33
- title: 'Beranda'
34
- },
35
- {
36
- children: [
37
- {
38
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
39
- slug: 'profil-daerah-irigasi',
40
- title: 'Profil Daerah Irigasi'
41
- },
42
- {
43
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
44
- slug: 'infrastruktur-irigasi',
45
- title: 'Infrastruktur Irigasi'
46
- },
47
- {
48
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
49
- slug: 'skema-jaringan-irigasi',
50
- title: 'Skema Jaringan Irigasi'
51
- }
52
- ],
53
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
54
- title: 'Daerah Irigasi'
55
- },
56
- {
57
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
58
- slug: 'debit-klimatologi',
59
- title: 'Debit & Klimatologi'
60
- },
61
- {
62
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
63
- slug: 'rencana-pola-tanam',
64
- title: 'Rencana Pola Tanam'
65
- },
66
- {
67
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
68
- slug: 'laporan',
69
- title: 'Laporan'
70
- },
71
- {
72
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
73
- slug: 'monitoring',
74
- title: 'Monitoring'
75
- },
76
- {
77
- icon: '<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">\n\t<g clip-path="url(#clip0_6267_47931)">\n\t\t<rect width="16" height="16" transform="translate(0 0.5)" fill="white" fill-opacity="0.01" />\n\t\t<path\n\t\t\td="M11.4194 1.5C11.5956 1.50006 11.7689 1.54723 11.9213 1.63574C12.0736 1.7242 12.2001 1.85099 12.2875 2.00391L15.7162 8.00391C15.8025 8.15491 15.848 8.3261 15.8481 8.5C15.8481 8.67397 15.8025 8.84503 15.7162 8.99609L12.2875 14.9961C12.2001 15.1491 12.0738 15.2767 11.9213 15.3652C11.7689 15.4537 11.5956 15.4999 11.4194 15.5H4.57953C4.40331 15.4999 4.22997 15.4537 4.07758 15.3652C3.92519 15.2767 3.79877 15.1491 3.71136 14.9961L0.28363 8.99609C0.197374 8.84505 0.151794 8.67394 0.151794 8.5C0.15183 8.3261 0.197373 8.15491 0.28363 8.00391L3.71136 2.00391C3.79872 1.85101 3.92533 1.72422 4.07758 1.63574C4.22997 1.54725 4.40331 1.50008 4.57953 1.5H11.4194ZM4.57953 2.5L1.15179 8.5L4.57953 14.5H11.4194L14.8481 8.5L11.4194 2.5H4.57953ZM7.6264 5.07422C8.08711 5.01559 8.55481 5.04987 9.00238 5.17383C9.45007 5.29785 9.86888 5.50944 10.2338 5.79688C10.5988 6.0844 10.9029 6.44234 11.1284 6.84863C11.5851 7.65204 11.7055 8.60324 11.4633 9.49512C11.2212 10.387 10.6367 11.1473 9.83636 11.6094C9.03607 12.0714 8.08526 12.198 7.19183 11.9619C6.29844 11.7257 5.53526 11.1458 5.06781 10.3486C4.82861 9.95028 4.67052 9.50771 4.60394 9.04785C4.5374 8.58808 4.56376 8.11968 4.68011 7.66992C4.7965 7.22008 5.0014 6.7976 5.28265 6.42773C5.56383 6.05806 5.91561 5.74791 6.31781 5.51562C6.72019 5.28326 7.16547 5.13294 7.6264 5.07422ZM8.73871 6.19336C8.10166 6.02041 7.42195 6.10738 6.84808 6.43359C6.56147 6.59655 6.30985 6.81463 6.10785 7.0752C5.90593 7.33569 5.75673 7.63311 5.67035 7.95117C5.58397 8.26934 5.56145 8.60178 5.60394 8.92871C5.64644 9.25566 5.75354 9.57092 5.9184 9.85645C6.08325 10.142 6.30298 10.3925 6.56488 10.5928C6.82672 10.7929 7.12613 10.9392 7.44476 11.0234C7.76338 11.1076 8.09579 11.1277 8.4223 11.083C8.74882 11.0383 9.06377 10.9304 9.34808 10.7637C9.91754 10.4298 10.3317 9.88331 10.5004 9.24512C10.669 8.60701 10.5785 7.92804 10.2485 7.35645C9.91843 6.7848 9.37571 6.36637 8.73871 6.19336Z"\n\t\t\tfill="#212529"\n\t\t/>\n\t</g>\n\t<defs>\n\t\t<clipPath id="clip0_6267_47931">\n\t\t\t<rect width="16" height="16" fill="white" transform="translate(0 0.5)" />\n\t\t</clipPath>\n\t</defs>\n</svg>',
78
- slug: 'pengaturan',
79
- title: 'Pengaturan'
80
- }
81
- ],
82
- user: {
83
- avatarUrl: 'https://storage.mertani.my.id/user-photo-10ca5eb5-5e49-45bc-abc4-59c99657a859',
84
- name: 'You rooot',
85
- role: 'admin-mertani'
86
- },
87
- }
88
- };