lula2 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. package/README.md +291 -8
  2. package/dist/_app/env.js +1 -0
  3. package/dist/_app/immutable/assets/0.DtiRW3lO.css +1 -0
  4. package/dist/_app/immutable/assets/DynamicControlEditor.BkVTzFZ-.css +1 -0
  5. package/dist/_app/immutable/chunks/7x_q-1ab.js +1 -0
  6. package/dist/_app/immutable/chunks/B19gt6-g.js +2 -0
  7. package/dist/_app/immutable/chunks/BR-0Dorr.js +1 -0
  8. package/dist/_app/immutable/chunks/B_3ksxz5.js +2 -0
  9. package/dist/_app/immutable/chunks/Bg_R1qWi.js +3 -0
  10. package/dist/_app/immutable/chunks/D3aNP_lg.js +1 -0
  11. package/dist/_app/immutable/chunks/D4Q_ObIy.js +1 -0
  12. package/dist/_app/immutable/chunks/DsnmJJEf.js +1 -0
  13. package/dist/_app/immutable/chunks/XY2j_owG.js +66 -0
  14. package/dist/_app/immutable/chunks/rzN25oDf.js +1 -0
  15. package/dist/_app/immutable/entry/app.r0uOd9qg.js +2 -0
  16. package/dist/_app/immutable/entry/start.DvoqR0rc.js +1 -0
  17. package/dist/_app/immutable/nodes/0.Ct6FAss_.js +1 -0
  18. package/dist/_app/immutable/nodes/1.DLoKuy8Q.js +1 -0
  19. package/dist/_app/immutable/nodes/2.IRkwSmiB.js +1 -0
  20. package/dist/_app/immutable/nodes/3.BrTg-ZHv.js +1 -0
  21. package/dist/_app/immutable/nodes/4.Blq-4WQS.js +9 -0
  22. package/dist/_app/version.json +1 -0
  23. package/dist/cli/commands/crawl.js +128 -0
  24. package/dist/cli/commands/ui.js +2769 -0
  25. package/dist/cli/commands/version.js +30 -0
  26. package/dist/cli/server/index.js +2713 -0
  27. package/dist/cli/server/server.js +2702 -0
  28. package/dist/cli/server/serverState.js +1199 -0
  29. package/dist/cli/server/spreadsheetRoutes.js +788 -0
  30. package/dist/cli/server/types.js +0 -0
  31. package/dist/cli/server/websocketServer.js +2625 -0
  32. package/dist/cli/utils/debug.js +24 -0
  33. package/dist/favicon.svg +1 -0
  34. package/dist/index.html +38 -0
  35. package/dist/index.js +2924 -37
  36. package/dist/lula.png +0 -0
  37. package/dist/lula2 +2 -0
  38. package/package.json +120 -72
  39. package/src/app.css +192 -0
  40. package/src/app.d.ts +13 -0
  41. package/src/app.html +13 -0
  42. package/src/lib/actions/fadeWhenScrollable.ts +39 -0
  43. package/src/lib/actions/modal.ts +230 -0
  44. package/src/lib/actions/tooltip.ts +82 -0
  45. package/src/lib/components/control-sets/ControlSetInfo.svelte +20 -0
  46. package/src/lib/components/control-sets/ControlSetSelector.svelte +46 -0
  47. package/src/lib/components/control-sets/index.ts +5 -0
  48. package/src/lib/components/controls/ControlDetailsPanel.svelte +235 -0
  49. package/src/lib/components/controls/ControlsList.svelte +608 -0
  50. package/src/lib/components/controls/DynamicControlEditor.svelte +298 -0
  51. package/src/lib/components/controls/MappingCard.svelte +105 -0
  52. package/src/lib/components/controls/MappingForm.svelte +188 -0
  53. package/src/lib/components/controls/index.ts +9 -0
  54. package/src/lib/components/controls/renderers/EditableFieldRenderer.svelte +103 -0
  55. package/src/lib/components/controls/renderers/FieldRenderer.svelte +49 -0
  56. package/src/lib/components/controls/renderers/index.ts +5 -0
  57. package/src/lib/components/controls/tabs/CustomFieldsTab.svelte +130 -0
  58. package/src/lib/components/controls/tabs/ImplementationTab.svelte +127 -0
  59. package/src/lib/components/controls/tabs/MappingsTab.svelte +182 -0
  60. package/src/lib/components/controls/tabs/OverviewTab.svelte +151 -0
  61. package/src/lib/components/controls/tabs/TimelineTab.svelte +41 -0
  62. package/src/lib/components/controls/tabs/index.ts +8 -0
  63. package/src/lib/components/controls/utils/ProcessedTextRenderer.svelte +63 -0
  64. package/src/lib/components/controls/utils/textProcessor.ts +164 -0
  65. package/src/lib/components/forms/DynamicControlForm.svelte +340 -0
  66. package/src/lib/components/forms/DynamicField.svelte +494 -0
  67. package/src/lib/components/forms/FormField.svelte +107 -0
  68. package/src/lib/components/forms/index.ts +6 -0
  69. package/src/lib/components/setup/ExistingControlSets.svelte +284 -0
  70. package/src/lib/components/setup/SpreadsheetImport.svelte +968 -0
  71. package/src/lib/components/setup/index.ts +5 -0
  72. package/src/lib/components/ui/Dropdown.svelte +107 -0
  73. package/src/lib/components/ui/EmptyState.svelte +80 -0
  74. package/src/lib/components/ui/FeatureToggle.svelte +50 -0
  75. package/src/lib/components/ui/SearchBar.svelte +73 -0
  76. package/src/lib/components/ui/StatusBadge.svelte +79 -0
  77. package/src/lib/components/ui/TabNavigation.svelte +48 -0
  78. package/src/lib/components/ui/Tooltip.svelte +120 -0
  79. package/src/lib/components/ui/index.ts +10 -0
  80. package/src/lib/components/version-control/DiffViewer.svelte +292 -0
  81. package/src/lib/components/version-control/TimelineItem.svelte +107 -0
  82. package/src/lib/components/version-control/YamlDiffViewer.svelte +428 -0
  83. package/src/lib/components/version-control/index.ts +6 -0
  84. package/src/lib/form-types.ts +57 -0
  85. package/src/lib/formatUtils.ts +17 -0
  86. package/src/lib/index.ts +5 -0
  87. package/src/lib/types.ts +180 -0
  88. package/src/lib/websocket.ts +359 -0
  89. package/src/routes/+layout.svelte +236 -0
  90. package/src/routes/+page.svelte +38 -0
  91. package/src/routes/control/[id]/+page.svelte +112 -0
  92. package/src/routes/setup/+page.svelte +241 -0
  93. package/src/stores/compliance.ts +95 -0
  94. package/src/styles/highlightjs.css +20 -0
  95. package/src/styles/modal.css +58 -0
  96. package/src/styles/tables.css +111 -0
  97. package/src/styles/tooltip.css +65 -0
  98. package/dist/controls/index.d.ts +0 -18
  99. package/dist/controls/index.d.ts.map +0 -1
  100. package/dist/controls/index.js +0 -18
  101. package/dist/crawl.d.ts +0 -62
  102. package/dist/crawl.d.ts.map +0 -1
  103. package/dist/crawl.js +0 -172
  104. package/dist/index.d.ts +0 -8
  105. package/dist/index.d.ts.map +0 -1
  106. package/src/controls/index.ts +0 -19
  107. package/src/crawl.ts +0 -227
  108. package/src/index.ts +0 -46
@@ -0,0 +1,284 @@
1
+ <script lang="ts">
2
+ import { onMount } from 'svelte';
3
+ import { createEventDispatcher } from 'svelte';
4
+ import { appState } from '$lib/websocket';
5
+
6
+ const dispatch = createEventDispatcher();
7
+
8
+ interface ControlSet {
9
+ path: string;
10
+ name: string;
11
+ description: string;
12
+ controlCount: number;
13
+ file: string;
14
+ }
15
+
16
+ export let controlSets: ControlSet[] = [];
17
+
18
+ let isLoading = false;
19
+ let errorMessage = '';
20
+ let selectedSet: ControlSet | null = null;
21
+
22
+ // Get current control set path from appState
23
+ $: currentPath = $appState.currentPath || '';
24
+
25
+ // React to control sets prop changes
26
+ $: if (controlSets) {
27
+ if (controlSets.length === 0) {
28
+ errorMessage = 'No existing control sets found. Try importing from a spreadsheet instead.';
29
+ } else {
30
+ // Find available control sets (not current)
31
+ const availableSets = controlSets.filter((cs) => !isCurrentControlSet(cs));
32
+ if (availableSets.length === 1) {
33
+ // Auto-select if only one non-current control set found
34
+ selectedSet = availableSets[0];
35
+ } else if (availableSets.length === 0 && controlSets.length > 0) {
36
+ // All control sets are current
37
+ errorMessage = 'already-using-only-set';
38
+ }
39
+ }
40
+ }
41
+
42
+ function selectControlSet(controlSet: ControlSet) {
43
+ // Don't select if it's the current control set
44
+ if (isCurrentControlSet(controlSet)) {
45
+ return;
46
+ }
47
+ selectedSet = controlSet;
48
+ }
49
+
50
+ function useSelectedControlSet() {
51
+ if (selectedSet && !isCurrentControlSet(selectedSet)) {
52
+ dispatch('selected', { path: selectedSet.path });
53
+ }
54
+ }
55
+
56
+ function isCurrentControlSet(controlSet: ControlSet): boolean {
57
+ // Check if this is the currently active control set
58
+ // Normalize paths for comparison (remove trailing slashes)
59
+ const normalizedCurrentPath = currentPath?.replace(/\/$/, '');
60
+ const normalizedControlSetPath = controlSet.path?.replace(/\/$/, '');
61
+
62
+ return !!(
63
+ normalizedCurrentPath &&
64
+ normalizedControlSetPath &&
65
+ normalizedCurrentPath === normalizedControlSetPath
66
+ );
67
+ }
68
+ </script>
69
+
70
+ <div class="space-y-6">
71
+ <div class="text-center">
72
+ <h2 class="text-2xl font-bold text-gray-900 dark:text-white mb-2">
73
+ Select an Existing Control Set
74
+ </h2>
75
+ <p class="text-gray-600 dark:text-gray-400">
76
+ Choose from control sets found in your project directory
77
+ </p>
78
+ </div>
79
+
80
+ {#if isLoading}
81
+ <div class="flex justify-center py-12">
82
+ <div class="text-center">
83
+ <svg
84
+ class="animate-spin h-8 w-8 text-blue-600 mx-auto mb-4"
85
+ xmlns="http://www.w3.org/2000/svg"
86
+ fill="none"
87
+ viewBox="0 0 24 24"
88
+ >
89
+ <circle class="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" stroke-width="4"
90
+ ></circle>
91
+ <path
92
+ class="opacity-75"
93
+ fill="currentColor"
94
+ d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
95
+ ></path>
96
+ </svg>
97
+ <p class="text-gray-500 dark:text-gray-400">Scanning for control sets...</p>
98
+ </div>
99
+ </div>
100
+ {:else if errorMessage === 'already-using-only-set'}
101
+ <div class="text-center space-y-6">
102
+ <div
103
+ class="p-6 bg-gradient-to-br from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 rounded-lg border-2 border-green-500"
104
+ >
105
+ <svg
106
+ class="w-12 h-12 text-green-600 mx-auto mb-4"
107
+ fill="currentColor"
108
+ viewBox="0 0 20 20"
109
+ xmlns="http://www.w3.org/2000/svg"
110
+ >
111
+ <path
112
+ fill-rule="evenodd"
113
+ d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
114
+ clip-rule="evenodd"
115
+ ></path>
116
+ </svg>
117
+ <h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-2">
118
+ Already Using Control Set
119
+ </h3>
120
+ <p class="text-gray-600 dark:text-gray-400 mb-4">
121
+ You are already using the only available control set in this project.
122
+ </p>
123
+ {#if controlSets.length > 0}
124
+ <div class="text-sm text-gray-500 dark:text-gray-400">
125
+ <span class="font-medium">{controlSets[0].name}</span>
126
+ {#if controlSets[0].controlCount}
127
+ <span class="ml-2">({controlSets[0].controlCount} controls)</span>
128
+ {/if}
129
+ </div>
130
+ {/if}
131
+ </div>
132
+
133
+ <div class="flex justify-center gap-4">
134
+ <a
135
+ href="/"
136
+ class="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors shadow-lg"
137
+ >
138
+ Continue to Controls
139
+ </a>
140
+ <button
141
+ on:click={() => dispatch('tab-change', { tab: 'import' })}
142
+ class="px-6 py-3 bg-gray-200 hover:bg-gray-300 dark:bg-gray-700 dark:hover:bg-gray-600 text-gray-900 dark:text-white font-medium rounded-lg transition-colors"
143
+ >
144
+ Import New Control Set
145
+ </button>
146
+ </div>
147
+ </div>
148
+ {:else if errorMessage}
149
+ <div
150
+ class="p-4 text-sm text-yellow-800 rounded-lg bg-yellow-50 dark:bg-gray-800 dark:text-yellow-300"
151
+ >
152
+ <div class="flex items-center">
153
+ <svg
154
+ class="flex-shrink-0 inline w-4 h-4 mr-3"
155
+ aria-hidden="true"
156
+ xmlns="http://www.w3.org/2000/svg"
157
+ fill="currentColor"
158
+ viewBox="0 0 20 20"
159
+ >
160
+ <path
161
+ d="M10 .5a9.5 9.5 0 1 0 9.5 9.5A9.51 9.51 0 0 0 10 .5ZM9.5 4a1.5 1.5 0 1 1 0 3 1.5 1.5 0 0 1 0-3ZM12 15H8a1 1 0 0 1 0-2h1v-3H8a1 1 0 0 1 0-2h2a1 1 0 0 1 1 1v4h1a1 1 0 0 1 0 2Z"
162
+ />
163
+ </svg>
164
+ <span>{errorMessage}</span>
165
+ </div>
166
+ </div>
167
+ {:else if controlSets.length > 0}
168
+ <div class="space-y-3">
169
+ {#each controlSets as controlSet}
170
+ {@const isCurrent = isCurrentControlSet(controlSet)}
171
+ <div
172
+ on:click={() => !isCurrent && selectControlSet(controlSet)}
173
+ on:keydown={(e) => e.key === 'Enter' && !isCurrent && selectControlSet(controlSet)}
174
+ role="button"
175
+ tabindex="0"
176
+ class="p-4 bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-800 dark:to-gray-900 rounded-lg border-2 transition-all duration-200 {isCurrent
177
+ ? 'border-green-500 !bg-gradient-to-br from-green-50 to-emerald-50 dark:from-green-900/20 dark:to-emerald-900/20 cursor-not-allowed opacity-75'
178
+ : selectedSet === controlSet
179
+ ? 'border-blue-500 !bg-gradient-to-br from-blue-50 to-indigo-50 dark:from-blue-900/20 dark:to-indigo-900/20 shadow-lg cursor-pointer'
180
+ : 'border-gray-200 dark:border-gray-700 hover:border-blue-300 dark:hover:border-blue-700 hover:shadow-md cursor-pointer'}"
181
+ >
182
+ <div class="flex items-center justify-between">
183
+ <div class="flex-1">
184
+ <div class="flex items-center gap-3">
185
+ <h3 class="text-lg font-semibold text-gray-900 dark:text-white">
186
+ {controlSet.name}
187
+ </h3>
188
+ <span
189
+ class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200"
190
+ >
191
+ {controlSet.controlCount || 0} controls
192
+ </span>
193
+ </div>
194
+
195
+ {#if controlSet.description}
196
+ <p class="text-sm text-gray-600 dark:text-gray-400 mt-1">
197
+ {controlSet.description}
198
+ </p>
199
+ {/if}
200
+
201
+ <div class="flex items-center gap-4 mt-2">
202
+ <span class="text-xs text-gray-500 dark:text-gray-400">
203
+ <svg class="inline w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20">
204
+ <path
205
+ fill-rule="evenodd"
206
+ d="M2 6a2 2 0 012-2h12a2 2 0 012 2v8a2 2 0 01-2 2H4a2 2 0 01-2-2V6zm2-1a1 1 0 00-1 1v8a1 1 0 001 1h12a1 1 0 001-1V6a1 1 0 00-1-1H4z"
207
+ clip-rule="evenodd"
208
+ />
209
+ </svg>
210
+ {controlSet.path || 'root'}
211
+ </span>
212
+ {#if controlSet.file}
213
+ <span class="text-xs text-gray-500 dark:text-gray-400">
214
+ <svg class="inline w-3 h-3 mr-1" fill="currentColor" viewBox="0 0 20 20">
215
+ <path
216
+ fill-rule="evenodd"
217
+ d="M4 3a2 2 0 00-2 2v10a2 2 0 002 2h12a2 2 0 002-2V5a2 2 0 00-2-2H4zm12 12H4l4-8 3 6 2-4 3 6z"
218
+ clip-rule="evenodd"
219
+ />
220
+ </svg>
221
+ {controlSet.file}
222
+ </span>
223
+ {/if}
224
+ </div>
225
+ </div>
226
+
227
+ <div class="flex items-center ml-4">
228
+ {#if isCurrent}
229
+ <div class="flex flex-col items-center">
230
+ <svg
231
+ class="w-8 h-8 text-green-600"
232
+ fill="currentColor"
233
+ viewBox="0 0 20 20"
234
+ xmlns="http://www.w3.org/2000/svg"
235
+ >
236
+ <path
237
+ fill-rule="evenodd"
238
+ d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
239
+ clip-rule="evenodd"
240
+ ></path>
241
+ </svg>
242
+ <span class="text-xs text-green-600 font-medium mt-1">Current</span>
243
+ </div>
244
+ {:else if selectedSet === controlSet}
245
+ <svg
246
+ class="w-8 h-8 text-blue-600"
247
+ fill="currentColor"
248
+ viewBox="0 0 20 20"
249
+ xmlns="http://www.w3.org/2000/svg"
250
+ >
251
+ <path
252
+ fill-rule="evenodd"
253
+ d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
254
+ clip-rule="evenodd"
255
+ ></path>
256
+ </svg>
257
+ {:else}
258
+ <svg
259
+ class="w-8 h-8 text-gray-300 dark:text-gray-600"
260
+ fill="none"
261
+ viewBox="0 0 20 20"
262
+ xmlns="http://www.w3.org/2000/svg"
263
+ >
264
+ <circle cx="10" cy="10" r="9" stroke="currentColor" stroke-width="2" />
265
+ </svg>
266
+ {/if}
267
+ </div>
268
+ </div>
269
+ </div>
270
+ {/each}
271
+ </div>
272
+
273
+ {#if selectedSet}
274
+ <div class="mt-6 flex justify-center">
275
+ <button
276
+ on:click={useSelectedControlSet}
277
+ class="px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-medium rounded-lg transition-colors shadow-lg"
278
+ >
279
+ Use Selected Control Set
280
+ </button>
281
+ </div>
282
+ {/if}
283
+ {/if}
284
+ </div>