oc 0.50.48 → 0.50.49

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 (51) hide show
  1. package/.turbo/turbo-build.log +18 -0
  2. package/.turbo/turbo-lint.log +5 -0
  3. package/.turbo/turbo-test-silent.log +43 -0
  4. package/.turbo/turbo-test.log +1612 -0
  5. package/CHANGELOG.md +385 -13
  6. package/README.md +4 -4
  7. package/dist/cli/domain/registry.js +5 -5
  8. package/dist/cli/facade/dev.js +1 -1
  9. package/dist/cli/facade/publish.js +1 -1
  10. package/dist/components/oc-client/_package/package.json +4 -4
  11. package/dist/components/oc-client/_package/server.js +1 -1
  12. package/dist/components/oc-client/_package/src/oc-client.js +7 -133
  13. package/dist/components/oc-client/_package/src/oc-client.min.js +1 -15
  14. package/dist/components/oc-client/_package/src/oc-client.min.map +1 -1
  15. package/dist/components/oc-client/package.json +1 -1
  16. package/dist/components/oc-client/src/oc-client.js +7 -133
  17. package/dist/components/oc-client/src/oc-client.min.js +1 -15
  18. package/dist/components/oc-client/src/oc-client.min.map +1 -1
  19. package/dist/registry/domain/components-details.js +44 -10
  20. package/dist/registry/domain/nested-renderer.js +1 -1
  21. package/dist/registry/domain/repository.js +15 -4
  22. package/dist/registry/domain/url-builder.js +1 -1
  23. package/dist/registry/domain/validators/registry-configuration.js +3 -4
  24. package/dist/registry/routes/component-info.js +1 -1
  25. package/dist/registry/routes/helpers/format-error-stack.js +0 -31
  26. package/dist/registry/routes/helpers/get-component.js +37 -26
  27. package/dist/registry/routes/index.js +1 -1
  28. package/dist/registry/routes/validate.js +1 -1
  29. package/dist/registry/views/partials/components-list.js +1 -1
  30. package/dist/registry/views/static/index.d.ts +1 -1
  31. package/dist/registry/views/static/index.js +39 -5
  32. package/dist/registry/views/static/style.d.ts +1 -1
  33. package/dist/registry/views/static/style.js +20 -16
  34. package/dist/utils/clean-require.js +1 -1
  35. package/dist/utils/module-exists.js +1 -1
  36. package/package.json +121 -128
  37. package/tsconfig.json +33 -33
  38. package/.editorconfig +0 -9
  39. package/.github/ISSUE_TEMPLATE.md +0 -29
  40. package/.github/PULL_REQUEST_TEMPLATE.md +0 -21
  41. package/.github/workflows/node.js.yml +0 -29
  42. package/.nvmrc +0 -1
  43. package/.prettierrc +0 -8
  44. package/.yarnrc.yml +0 -1
  45. package/AGENTS.md +0 -58
  46. package/CONTRIBUTING.md +0 -68
  47. package/LICENSE +0 -20
  48. package/biome.json +0 -52
  49. package/lefthook.yml +0 -5
  50. package/logo-type.png +0 -0
  51. package/logo.png +0 -0
@@ -63,6 +63,23 @@ const get_component_retrieving_info_1 = __importDefault(require("./get-component
63
63
  exports.stream = Symbol('stream');
64
64
  const noop = () => { };
65
65
  const noopConsole = Object.fromEntries(Object.keys(console).map((key) => [key, noop]));
66
+ const parseTemplatesHeader = (templates) => {
67
+ const result = [];
68
+ let start = 0;
69
+ for (let index = 0; index <= templates.length; index++) {
70
+ const char = templates[index];
71
+ if (char === ',' || char === ';' || index === templates.length) {
72
+ result.push(templates.slice(start, index));
73
+ start = templates.indexOf(';', index);
74
+ if (start === -1) {
75
+ break;
76
+ }
77
+ index = start;
78
+ start++;
79
+ }
80
+ }
81
+ return result;
82
+ };
66
83
  /**
67
84
  * Converts the plugins to a function that returns a record of plugins with the context applied
68
85
  * Caches the plugins without context and applies the context to the plugins that need it
@@ -143,6 +160,9 @@ function getComponent(conf, repository) {
143
160
  };
144
161
  let componentCallbackDone = false;
145
162
  const conf = options.conf;
163
+ const customHeadersToSkipSet = conf.customHeadersToSkipOnWeakVersion?.length
164
+ ? new Set(conf.customHeadersToSkipOnWeakVersion)
165
+ : undefined;
146
166
  const acceptLanguage = getLanguage();
147
167
  const requestedComponent = {
148
168
  name: options.name,
@@ -218,7 +238,8 @@ function getComponent(conf, repository) {
218
238
  if (isLegacyTemplate) {
219
239
  templateType = `oc-template-${templateType}`;
220
240
  }
221
- if (!repository.getTemplate(templateType)) {
241
+ const ocTemplate = repository.getTemplate(templateType);
242
+ if (!ocTemplate) {
222
243
  return callback({
223
244
  status: 400,
224
245
  response: {
@@ -228,12 +249,17 @@ function getComponent(conf, repository) {
228
249
  });
229
250
  }
230
251
  const filterCustomHeaders = (headers, requestedVersion, actualVersion) => {
231
- const needFiltering = Object.keys(headers).length > 0 &&
232
- conf.customHeadersToSkipOnWeakVersion?.length > 0 &&
233
- requestedVersion !== actualVersion;
234
- if (!needFiltering)
252
+ if (!customHeadersToSkipSet || requestedVersion === actualVersion) {
235
253
  return headers;
236
- return Object.fromEntries(Object.entries(headers).filter(([key]) => !conf.customHeadersToSkipOnWeakVersion.includes(key)));
254
+ }
255
+ let filteredHeaders;
256
+ for (const key in headers) {
257
+ if (!customHeadersToSkipSet.has(key)) {
258
+ filteredHeaders = filteredHeaders || {};
259
+ filteredHeaders[key] = headers[key];
260
+ }
261
+ }
262
+ return filteredHeaders || {};
237
263
  };
238
264
  const returnComponent = async (err, data) => {
239
265
  if (componentCallbackDone) {
@@ -248,10 +274,8 @@ function getComponent(conf, repository) {
248
274
  const isUnrendered = options.headers.accept === settings_1.default.registry.acceptUnrenderedHeader;
249
275
  const isValidClientRequest = options.headers['user-agent'] &&
250
276
  !!options.headers['user-agent'].match('oc-client-');
251
- const parseTemplatesHeader = (t) => t.split(';').map((t) => t.split(',')[0]);
252
277
  const supportedTemplates = options.headers['templates']
253
- ? (parseTemplatesHeader(options.headers['templates']) ??
254
- [])
278
+ ? parseTemplatesHeader(options.headers['templates'])
255
279
  : [];
256
280
  const isTemplateSupportedByClient = Boolean(isValidClientRequest &&
257
281
  options.headers['templates'] &&
@@ -271,7 +295,7 @@ function getComponent(conf, repository) {
271
295
  version: component.version,
272
296
  renderMode
273
297
  });
274
- if (!!err || !data) {
298
+ if (err || !data) {
275
299
  err =
276
300
  err ||
277
301
  new Error(resources_1.default.errors.registry.DATA_OBJECT_IS_UNDEFINED);
@@ -377,24 +401,11 @@ function getComponent(conf, repository) {
377
401
  });
378
402
  });
379
403
  };
380
- if (!!cached && !conf.hotReloading) {
404
+ if (cached && !conf.hotReloading) {
381
405
  returnResult(cached);
382
406
  }
383
407
  else {
384
408
  (0, universalify_1.fromPromise)(repository.getCompiledView)(component.name, component.version, (_err, templateText) => {
385
- let ocTemplate;
386
- try {
387
- ocTemplate = repository.getTemplate(templateType);
388
- }
389
- catch {
390
- return callback({
391
- status: 400,
392
- response: {
393
- code: 'TEMPLATE_NOT_SUPPORTED',
394
- error: resources_1.default.errors.registry.TEMPLATE_NOT_SUPPORTED(templateType)
395
- }
396
- });
397
- }
398
409
  const template = ocTemplate.getCompiledTemplate(templateText, key);
399
410
  cache.set('file-contents', cacheKey, template);
400
411
  returnResult(template);
@@ -404,7 +415,7 @@ function getComponent(conf, repository) {
404
415
  };
405
416
  const staticPath = repository
406
417
  .getStaticFilePath(component.name, component.version, '')
407
- .replace('https:', '');
418
+ .replace(/^https:/, '');
408
419
  if (!component.oc.files.dataProvider) {
409
420
  const { __oc_Retry, ...props } = params;
410
421
  props['_staticPath'] = staticPath;
@@ -475,7 +486,7 @@ function getComponent(conf, repository) {
475
486
  }, executionTimeout * 1000);
476
487
  }
477
488
  };
478
- if (!!cached && !conf.hotReloading) {
489
+ if (cached && !conf.hotReloading) {
479
490
  domain.on('error', returnComponent);
480
491
  try {
481
492
  domain.run(() => {
@@ -36,7 +36,7 @@ function default_1(repository) {
36
36
  type: res.conf.local ? 'oc-registry-local' : 'oc-registry'
37
37
  };
38
38
  const componentDetails = await Promise.all(componentNames.map((componentName) => repository.getComponent(componentName, undefined)));
39
- if (isHtmlRequest(req.headers) && !!res.conf.discovery.ui) {
39
+ if (isHtmlRequest(req.headers) && res.conf.discovery.ui) {
40
40
  const processedComponents = componentDetails.map((component) => {
41
41
  if (component.oc?.date) {
42
42
  component.oc.stringifiedDate = (0, date_stringify_1.default)(new Date(component.oc.date));
@@ -43,7 +43,7 @@ const validators_1 = require("../domain/validators");
43
43
  function validate() {
44
44
  return async (req, res) => {
45
45
  // Validate that request has a JSON body with package.json
46
- if (!req.body || !req.body.packageJson) {
46
+ if (!req.body?.packageJson) {
47
47
  res.status(400).json({
48
48
  error: 'Invalid request: packageJson is required in request body'
49
49
  });
@@ -17,6 +17,6 @@ const ComponentsList = (props) => {
17
17
  ? `${Math.round(component.oc.files.template.size / 1024)} kb`
18
18
  : '? Kb' }))] }) })] }) }));
19
19
  };
20
- return ((0, jsx_runtime_1.jsxs)("div", { id: "components-list", class: "box", children: [(0, jsx_runtime_1.jsxs)("form", { id: "filter-components", children: [(0, jsx_runtime_1.jsxs)("div", { class: "filters", children: [(0, jsx_runtime_1.jsx)("input", { id: "search-filter", type: "text", autofocus: true, placeholder: "Filter by component name" }), (0, jsx_runtime_1.jsx)("input", { id: "author-filter", type: "text", placeholder: "Filter by component author" })] }), (0, jsx_runtime_1.jsxs)("div", { class: "states", children: [(0, jsx_runtime_1.jsx)("span", { children: "Hide:" }), (0, jsx_runtime_1.jsx)(selected_checkbox_1.default, { name: "deprecated", stateCounts: props.stateCounts }), (0, jsx_runtime_1.jsx)(selected_checkbox_1.default, { name: "experimental", stateCounts: props.stateCounts })] })] }), (0, jsx_runtime_1.jsxs)("div", { class: "row header componentRow table", children: [(0, jsx_runtime_1.jsx)("div", { class: "title" }), (0, jsx_runtime_1.jsx)("div", { class: "author", children: "Author" }), (0, jsx_runtime_1.jsx)("div", { children: "Latest version" }), isRemote && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { class: "date", children: "Updated" }), (0, jsx_runtime_1.jsx)("div", { class: "activity", children: "Activity" })] })), sizeAvailable && (0, jsx_runtime_1.jsx)("div", { children: "Size" })] }), props.components.map(componentRow)] }));
20
+ return ((0, jsx_runtime_1.jsxs)("div", { id: "components-list", class: "box", children: [(0, jsx_runtime_1.jsxs)("form", { id: "filter-components", children: [(0, jsx_runtime_1.jsxs)("div", { class: "filters", children: [(0, jsx_runtime_1.jsx)("input", { id: "search-filter", type: "text", "aria-label": "Filter by component name", placeholder: "Filter by component name" }), (0, jsx_runtime_1.jsx)("input", { id: "author-filter", type: "text", "aria-label": "Filter by component author", placeholder: "Filter by component author" })] }), (0, jsx_runtime_1.jsxs)("div", { class: "states", children: [(0, jsx_runtime_1.jsx)("span", { children: "Hide:" }), (0, jsx_runtime_1.jsx)(selected_checkbox_1.default, { name: "deprecated", stateCounts: props.stateCounts }), (0, jsx_runtime_1.jsx)(selected_checkbox_1.default, { name: "experimental", stateCounts: props.stateCounts })] })] }), (0, jsx_runtime_1.jsxs)("div", { class: "row header componentRow table", children: [(0, jsx_runtime_1.jsx)("div", { class: "title" }), (0, jsx_runtime_1.jsx)("div", { class: "author", children: "Author" }), (0, jsx_runtime_1.jsx)("div", { children: "Latest version" }), isRemote && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { class: "date", children: "Updated" }), (0, jsx_runtime_1.jsx)("div", { class: "activity", children: "Activity" })] })), sizeAvailable && (0, jsx_runtime_1.jsx)("div", { children: "Size" })] }), props.components.map(componentRow)] }));
21
21
  };
22
22
  exports.default = ComponentsList;
@@ -1,2 +1,2 @@
1
- declare const _default: "'use strict';\n\nvar oc = oc || {};\noc.cmd = oc.cmd || [];\n\noc.cmd.push(function() {\n var componentsListChanged = function() {\n $('.componentRow').removeClass('hide');\n var s = $('#search-filter').val(),\n a = $('#author-filter').val(),\n r = new RegExp(s),\n ar = new RegExp(a, 'i'),\n selectedCheckboxes = $('input[type=checkbox]:checked'),\n hiddenStates = [],\n hidden = 0,\n i;\n\n for (i = 0; i < selectedCheckboxes.length; i++) {\n hiddenStates.push($(selectedCheckboxes[i]).attr('name'));\n }\n\n for (i = 0; i < componentsList.length; i++) {\n var matches = !s || !!componentsList[i].name.match(r),\n matchesAuthor =\n !a ||\n (componentsList[i].author.name &&\n !!componentsList[i].author.name.match(ar)),\n selector = $('#component-' + componentsList[i].name),\n isHidden = false;\n\n for (var j = 0; j < hiddenStates.length; j++) {\n if (componentsList[i].state.toLowerCase() === hiddenStates[j]) {\n isHidden = true;\n }\n }\n\n var show = matches && matchesAuthor && !isHidden;\n selector[show ? 'removeClass' : 'addClass']('hide');\n if (!show) {\n hidden += 1;\n }\n }\n\n var totalShowing = componentsList.length - hidden,\n result = 'Showing ' + totalShowing + ' components';\n\n if (s) {\n result += ' matching search query: \"' + s + '\"';\n if (a) {\n result += ' and';\n }\n }\n if (a) {\n result += ' matching author query: \"' + a + '\"';\n }\n\n $('.componentRow.header .title').text(result);\n\n return false;\n };\n\n var historyData = [];\n var historyRenderedCount = 0;\n var historyBatchSize = 50; // Number of items to render per batch\n var isLoadingMore = false;\n\n var renderHistoryBatch = function() {\n if (historyRenderedCount >= historyData.length || isLoadingMore) {\n return;\n }\n\n isLoadingMore = true;\n var historyContent = $('#history-content');\n var batchEnd = Math.min(historyRenderedCount + historyBatchSize, historyData.length);\n var batchHtml = '';\n\n for (var i = historyRenderedCount; i < batchEnd; i++) {\n var item = historyData[i];\n var templateSizeText = item.templateSize ? \n ' [' + Math.round(item.templateSize / 1024) + ' kb]' : '';\n \n batchHtml += '<a href=\"' + item.name + '/' + item.version + '/~info\">' +\n '<div class=\"componentRow row table\">' +\n '<p class=\"release\">' +\n item.publishDate + ' - Published ' + item.name + '@' + item.version +\n templateSizeText +\n '</p>' +\n '</div>' +\n '</a>';\n }\n\n // Append new batch to existing content\n historyContent.append(batchHtml);\n historyRenderedCount = batchEnd;\n \n // Add loading indicator if there are more items\n if (historyRenderedCount < historyData.length) {\n historyContent.append('<div id=\"history-loading-more\" class=\"loading-more\">Loading more...</div>');\n }\n \n isLoadingMore = false;\n };\n\n var setupHistoryScrollListener = function() {\n var historyContainer = $('#components-history');\n var checkScroll = function() {\n if (historyRenderedCount >= historyData.length) {\n return;\n }\n\n var containerTop = historyContainer.offset().top;\n var containerHeight = historyContainer.outerHeight();\n var scrollTop = $(window).scrollTop();\n var windowHeight = $(window).height();\n \n // Check if user scrolled close to the bottom of the history container\n var distanceFromBottom = (containerTop + containerHeight) - (scrollTop + windowHeight);\n \n if (distanceFromBottom < 200) { // Load more when 200px from bottom\n $('#history-loading-more').remove();\n renderHistoryBatch();\n }\n };\n\n $(window).on('scroll.history', checkScroll);\n \n // Also check on resize\n $(window).on('resize.history', checkScroll);\n };\n\n var loadComponentsHistory = function() {\n var historyLoader = $('#history-loader');\n var historyContent = $('#history-content');\n var historyError = $('#history-error');\n\n // Show loader\n historyLoader.show();\n historyContent.hide();\n historyError.hide();\n\n // Reset state\n historyData = [];\n historyRenderedCount = 0;\n isLoadingMore = false;\n\n // Remove any existing scroll listeners\n $(window).off('scroll.history resize.history');\n\n // Fetch history data\n fetch('~registry/history')\n .then(function(response) {\n if (!response.ok) {\n throw new Error('Failed to fetch history');\n }\n return response.json();\n })\n .then(function(data) {\n historyData = data.componentsHistory || [];\n \n // Clear content and show container\n historyContent.empty();\n historyLoader.hide();\n historyContent.show();\n \n if (historyData.length === 0) {\n historyContent.html('<p style=\"text-align: center; color: #64748b; padding: 2em;\">No components history available.</p>');\n return;\n }\n\n // Render first batch\n renderHistoryBatch();\n \n // Setup scroll listener for infinite loading\n setupHistoryScrollListener();\n })\n .catch(function(error) {\n console.error('Error loading components history:', error);\n historyLoader.hide();\n historyError.show();\n });\n };\n\n var isHistoryLoaded = false;\n\n var initialiseTabs = function() {\n var selectItem = function(target) {\n var $target = $(target);\n $('.box').hide();\n $target.show();\n $('#menuList a').removeClass('selected');\n $('#menuList a[href=\"' + target + '\"]').addClass('selected');\n \n // Clean up scroll listeners when leaving history tab\n if (target !== '#components-history') {\n $(window).off('scroll.history resize.history');\n }\n \n // Load history data when history tab is selected for the first time\n if (target === '#components-history' && !isHistoryLoaded) {\n loadComponentsHistory();\n isHistoryLoaded = true;\n }\n // Re-enable scroll listeners when returning to history tab\n else if (target === '#components-history' && isHistoryLoaded && historyRenderedCount < historyData.length) {\n setupHistoryScrollListener();\n }\n };\n\n var hash = location.href.split('#')[1] || '';\n var isHashValid = hash && $('#' + hash);\n var target = isHashValid ? '#' + hash : $($('#menuList a')[0]).attr('href');\n selectItem(target);\n\n $('#menuList a').click(function() {\n selectItem($(this).attr('href'));\n });\n };\n\n $('#filter-components')\n .submit(componentsListChanged)\n .keyup(componentsListChanged);\n $('#filter-components input[type=checkbox]').change(componentsListChanged);\n\n if (q) {\n $('.search').val(q);\n }\n\n componentsListChanged();\n initialiseTabs();\n});";
1
+ declare const _default: "'use strict';\n\nvar oc = oc || {};\noc.cmd = oc.cmd || [];\n\noc.cmd.push(function() {\n var escapeRegExp = function(s) {\n return String(s).replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n };\n\n var safeRegExp = function(pattern, flags) {\n try {\n return new RegExp(pattern, flags);\n } catch (e) {\n return new RegExp(escapeRegExp(pattern), flags);\n }\n };\n\n var componentsListChanged = function() {\n $('.componentRow').removeClass('hide');\n var s = $('#search-filter').val(),\n a = $('#author-filter').val(),\n r = safeRegExp(s, ''),\n ar = safeRegExp(a, 'i'),\n selectedCheckboxes = $('input[type=checkbox]:checked'),\n hiddenStates = [],\n hidden = 0,\n i;\n\n for (i = 0; i < selectedCheckboxes.length; i++) {\n hiddenStates.push($(selectedCheckboxes[i]).attr('name'));\n }\n\n for (i = 0; i < componentsList.length; i++) {\n var matches = !s || !!componentsList[i].name.match(r),\n matchesAuthor =\n !a ||\n (componentsList[i].author.name &&\n !!componentsList[i].author.name.match(ar)),\n selector = $('#component-' + componentsList[i].name),\n isHidden = false;\n\n for (var j = 0; j < hiddenStates.length; j++) {\n if (componentsList[i].state.toLowerCase() === hiddenStates[j]) {\n isHidden = true;\n }\n }\n\n var show = matches && matchesAuthor && !isHidden;\n selector[show ? 'removeClass' : 'addClass']('hide');\n if (!show) {\n hidden += 1;\n }\n }\n\n var totalShowing = componentsList.length - hidden,\n result = 'Showing ' + totalShowing + ' components';\n\n if (s) {\n result += ' matching search query: \"' + s + '\"';\n if (a) {\n result += ' and';\n }\n }\n if (a) {\n result += ' matching author query: \"' + a + '\"';\n }\n\n $('.componentRow.header .title').text(result);\n\n return false;\n };\n\n var historyData = [];\n var historyRenderedCount = 0;\n var historyBatchSize = 50; // Number of items to render per batch\n var isLoadingMore = false;\n\n var renderHistoryBatch = function() {\n if (historyRenderedCount >= historyData.length || isLoadingMore) {\n return;\n }\n\n isLoadingMore = true;\n var historyContent = $('#history-content');\n var batchEnd = Math.min(historyRenderedCount + historyBatchSize, historyData.length);\n var batchHtml = '';\n\n for (var i = historyRenderedCount; i < batchEnd; i++) {\n var item = historyData[i];\n var templateSizeText = item.templateSize ? \n ' [' + Math.round(item.templateSize / 1024) + ' kb]' : '';\n \n batchHtml += '<a href=\"' + item.name + '/' + item.version + '/~info\">' +\n '<div class=\"componentRow row table\">' +\n '<p class=\"release\">' +\n item.publishDate + ' - Published ' + item.name + '@' + item.version +\n templateSizeText +\n '</p>' +\n '</div>' +\n '</a>';\n }\n\n // Append new batch to existing content\n historyContent.append(batchHtml);\n historyRenderedCount = batchEnd;\n \n // Add loading indicator if there are more items\n if (historyRenderedCount < historyData.length) {\n historyContent.append('<div id=\"history-loading-more\" class=\"loading-more\">Loading more...</div>');\n }\n \n isLoadingMore = false;\n };\n\n var setupHistoryScrollListener = function() {\n var historyContainer = $('#components-history');\n var checkScroll = function() {\n if (historyRenderedCount >= historyData.length) {\n return;\n }\n\n var containerTop = historyContainer.offset().top;\n var containerHeight = historyContainer.outerHeight();\n var scrollTop = $(window).scrollTop();\n var windowHeight = $(window).height();\n \n // Check if user scrolled close to the bottom of the history container\n var distanceFromBottom = (containerTop + containerHeight) - (scrollTop + windowHeight);\n \n if (distanceFromBottom < 200) { // Load more when 200px from bottom\n $('#history-loading-more').remove();\n renderHistoryBatch();\n }\n };\n\n $(window).on('scroll.history', checkScroll);\n \n // Also check on resize\n $(window).on('resize.history', checkScroll);\n };\n\n var loadComponentsHistory = function() {\n var historyLoader = $('#history-loader');\n var historyContent = $('#history-content');\n var historyError = $('#history-error');\n\n // Show loader\n historyLoader.show();\n historyContent.hide();\n historyError.hide();\n\n // Reset state\n historyData = [];\n historyRenderedCount = 0;\n isLoadingMore = false;\n\n // Remove any existing scroll listeners\n $(window).off('scroll.history resize.history');\n\n // Fetch history data\n fetch('~registry/history')\n .then(function(response) {\n if (!response.ok) {\n throw new Error('Failed to fetch history');\n }\n return response.json();\n })\n .then(function(data) {\n historyData = data.componentsHistory || [];\n \n // Clear content and show container\n historyContent.empty();\n historyLoader.hide();\n historyContent.show();\n \n if (historyData.length === 0) {\n historyContent.html('<p class=\"empty-state\">No components history available.</p>');\n return;\n }\n\n // Render first batch\n renderHistoryBatch();\n \n // Setup scroll listener for infinite loading\n setupHistoryScrollListener();\n })\n .catch(function(error) {\n console.error('Error loading components history:', error);\n historyLoader.hide();\n historyError.show();\n });\n };\n\n var isHistoryLoaded = false;\n\n var initialiseTabs = function() {\n var selectItem = function(target) {\n var $target = $(target);\n $('.box').hide();\n $target.show();\n $('#menuList a').removeClass('selected');\n $('#menuList a[href=\"' + target + '\"]').addClass('selected');\n\n // Keep URL in sync so tab survives refresh and back/forward\n try {\n if (history && history.replaceState && location.hash !== target) {\n history.replaceState(null, '', target);\n }\n } catch (e) {}\n\n // Clean up scroll listeners when leaving history tab\n if (target !== '#components-history') {\n $(window).off('scroll.history resize.history');\n }\n \n // Load history data when history tab is selected for the first time\n if (target === '#components-history' && !isHistoryLoaded) {\n loadComponentsHistory();\n isHistoryLoaded = true;\n }\n // Re-enable scroll listeners when returning to history tab\n else if (target === '#components-history' && isHistoryLoaded && historyRenderedCount < historyData.length) {\n setupHistoryScrollListener();\n }\n };\n\n var hash = location.href.split('#')[1] || '';\n var isHashValid = hash && $('#' + hash);\n var target = isHashValid ? '#' + hash : $($('#menuList a')[0]).attr('href');\n selectItem(target);\n\n $('#menuList a').click(function() {\n selectItem($(this).attr('href'));\n });\n };\n\n var debounce = function(fn, wait) {\n var t;\n return function() {\n var ctx = this, args = arguments;\n clearTimeout(t);\n t = setTimeout(function(){ fn.apply(ctx, args); }, wait);\n };\n };\n\n $('#filter-components')\n .submit(componentsListChanged)\n .keyup(debounce(componentsListChanged, 80));\n $('#filter-components input[type=checkbox]').change(componentsListChanged);\n\n if (q) {\n $('.search').val(q);\n }\n\n // Focus the search input only on a fresh load (no tab hash, no in-page nav)\n if (!location.hash) {\n var $searchInput = $('#search-filter');\n if ($searchInput.length) { $searchInput.focus(); }\n }\n\n componentsListChanged();\n initialiseTabs();\n});";
2
2
  export default _default;
@@ -6,12 +6,24 @@ var oc = oc || {};
6
6
  oc.cmd = oc.cmd || [];
7
7
 
8
8
  oc.cmd.push(function() {
9
+ var escapeRegExp = function(s) {
10
+ return String(s).replace(/[.*+?^\${}()|[\\]\\\\]/g, '\\\\$&');
11
+ };
12
+
13
+ var safeRegExp = function(pattern, flags) {
14
+ try {
15
+ return new RegExp(pattern, flags);
16
+ } catch (e) {
17
+ return new RegExp(escapeRegExp(pattern), flags);
18
+ }
19
+ };
20
+
9
21
  var componentsListChanged = function() {
10
22
  $('.componentRow').removeClass('hide');
11
23
  var s = $('#search-filter').val(),
12
24
  a = $('#author-filter').val(),
13
- r = new RegExp(s),
14
- ar = new RegExp(a, 'i'),
25
+ r = safeRegExp(s, ''),
26
+ ar = safeRegExp(a, 'i'),
15
27
  selectedCheckboxes = $('input[type=checkbox]:checked'),
16
28
  hiddenStates = [],
17
29
  hidden = 0,
@@ -165,7 +177,7 @@ oc.cmd.push(function() {
165
177
  historyContent.show();
166
178
 
167
179
  if (historyData.length === 0) {
168
- historyContent.html('<p style="text-align: center; color: #64748b; padding: 2em;">No components history available.</p>');
180
+ historyContent.html('<p class="empty-state">No components history available.</p>');
169
181
  return;
170
182
  }
171
183
 
@@ -191,7 +203,14 @@ oc.cmd.push(function() {
191
203
  $target.show();
192
204
  $('#menuList a').removeClass('selected');
193
205
  $('#menuList a[href="' + target + '"]').addClass('selected');
194
-
206
+
207
+ // Keep URL in sync so tab survives refresh and back/forward
208
+ try {
209
+ if (history && history.replaceState && location.hash !== target) {
210
+ history.replaceState(null, '', target);
211
+ }
212
+ } catch (e) {}
213
+
195
214
  // Clean up scroll listeners when leaving history tab
196
215
  if (target !== '#components-history') {
197
216
  $(window).off('scroll.history resize.history');
@@ -218,15 +237,30 @@ oc.cmd.push(function() {
218
237
  });
219
238
  };
220
239
 
240
+ var debounce = function(fn, wait) {
241
+ var t;
242
+ return function() {
243
+ var ctx = this, args = arguments;
244
+ clearTimeout(t);
245
+ t = setTimeout(function(){ fn.apply(ctx, args); }, wait);
246
+ };
247
+ };
248
+
221
249
  $('#filter-components')
222
250
  .submit(componentsListChanged)
223
- .keyup(componentsListChanged);
251
+ .keyup(debounce(componentsListChanged, 80));
224
252
  $('#filter-components input[type=checkbox]').change(componentsListChanged);
225
253
 
226
254
  if (q) {
227
255
  $('.search').val(q);
228
256
  }
229
257
 
258
+ // Focus the search input only on a fresh load (no tab hash, no in-page nav)
259
+ if (!location.hash) {
260
+ var $searchInput = $('#search-filter');
261
+ if ($searchInput.length) { $searchInput.focus(); }
262
+ }
263
+
230
264
  componentsListChanged();
231
265
  initialiseTabs();
232
266
  });`;
@@ -1,2 +1,2 @@
1
- declare const _default: "\n@import url(\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap\");\n\n:root {\n /* Primary brand colors (consistent across themes) */\n --color-primary: #6366f1;\n --color-primary-dark: #4f46e5;\n --color-primary-light: #818cf8;\n --color-secondary: #06b6d4;\n --color-accent: #f59e0b;\n\n --gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);\n --gradient-secondary: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%);\n --gradient-accent: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n\n /* Legacy color mappings for backward compatibility */\n --color-warning: #ffe066;\n --color-warning-text: #7c3aed;\n --color-danger: #ffd6d6;\n --color-danger-text: #c92a2a;\n --color-state-border: #e9ecef;\n}\n\n/* Dark theme (default) */\n:root, [data-theme=\"dark\"] {\n --color-bg-primary: #0f0f23;\n --color-bg-secondary: #1a1a2e;\n --color-bg-card: #16213e;\n --color-bg-glass: rgba(255, 255, 255, 0.05);\n\n --color-text-primary: #ffffff;\n --color-text-secondary: #b4b4b8;\n --color-text-muted: #acacb9;\n\n --color-border: rgba(255, 255, 255, 0.1);\n --color-border-hover: rgba(255, 255, 255, 0.2);\n\n --gradient-card: rgba(255,255,255,0.03); /* Simplified from gradient */\n\n --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n --shadow-glow: 0 0 20px rgba(99, 102, 241, 0.3);\n\n /* Dark theme text inverse (for buttons, etc) */\n --color-text-inverse: #ffffff;\n}\n\n/* Light theme */\n[data-theme=\"light\"] {\n --color-bg-primary: #ffffff;\n --color-bg-secondary: #f8fafc;\n --color-bg-card: #ffffff;\n --color-bg-glass: rgba(255, 255, 255, 0.8);\n\n --color-text-primary: #1e293b;\n --color-text-secondary: #475569; /* Improved contrast from #64748b */\n --color-text-muted: #64748b; /* Improved contrast from #94a3b8 */\n\n --color-border: rgba(0, 0, 0, 0.1);\n --color-border-hover: rgba(0, 0, 0, 0.15);\n\n --gradient-card: rgba(0,0,0,0.02); /* Simplified from gradient */\n\n --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n --shadow-glow: 0 0 20px rgba(99, 102, 241, 0.2);\n\n /* Light theme text inverse (for buttons, etc) */\n --color-text-inverse: #ffffff;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n @view-transition {\n navigation: auto;\n }\n}\n\nbody {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n background: var(--color-bg-primary);\n color: var(--color-text-primary);\n line-height: 1.6;\n min-height: 100vh;\n overflow-x: hidden;\n}\n\n/* Animated background - Dark theme */\nbody::before {\n content: '';\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background:\n radial-gradient(circle at 20% 80%, rgba(99, 102, 241, 0.1) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(139, 92, 246, 0.1) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(6, 182, 212, 0.05) 0%, transparent 50%);\n z-index: -1;\n transition: opacity 0.3s ease;\n}\n\n/* Animated background - Light theme */\n[data-theme=\"light\"] body::before {\n background:\n radial-gradient(circle at 20% 80%, rgba(99, 102, 241, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(139, 92, 246, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(6, 182, 212, 0.02) 0%, transparent 50%);\n}\n\n.container {\n max-width: 1400px;\n margin: 0 auto;\n padding: 0 2rem;\n}\n\n/* Header */\n.header {\n background: var(--color-bg-glass);\n backdrop-filter: blur(20px);\n border-bottom: 1px solid var(--color-border);\n position: sticky;\n top: 0;\n z-index: 100;\n}\n\n.header-content {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 0;\n}\n\n.logo {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n text-decoration: none;\n color: var(--color-text-primary);\n font-weight: 700;\n font-size: 1.25rem;\n transition: all 0.3s ease;\n}\n\n.logo:hover {\n color: var(--color-primary-light);\n transform: translateY(-1px);\n}\n\n.logo-icon {\n color: #fff;\n width: 32px;\n height: 32px;\n background: var(--gradient-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: bold;\n font-size: 1.1rem;\n}\n\n.logo img {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n}\n\n/* Theme Toggle Button */\n.theme-toggle {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background: var(--color-bg-glass);\n border: 1px solid var(--color-border);\n border-radius: 8px;\n color: var(--color-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n transition: all 0.3s ease;\n cursor: pointer;\n backdrop-filter: blur(10px);\n}\n\n.theme-toggle:hover {\n border-color: var(--color-border-hover);\n background: var(--color-bg-card);\n transform: translateY(-1px);\n}\n\n.theme-toggle-icon {\n font-size: 1.1rem;\n transition: transform 0.3s ease;\n}\n\n.theme-toggle:hover .theme-toggle-icon {\n transform: rotate(180deg);\n}\n\nh1, h2, h3 {\n color: var(--color-text-primary);\n font-weight: 600;\n margin-bottom: 0.5em;\n}\n\nh1 {\n font-size: 3.5rem;\n font-weight: 700;\n background: var(--gradient-primary);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 1rem;\n text-align: center;\n}\n\nh2 {\n font-size: 1.5rem; /* Increased from 1.25rem */\n font-weight: 600;\n color: var(--color-text-primary);\n margin-bottom: 0.75em;\n}\n\nh3 {\n font-size: 1.25rem; /* Increased from 1.1rem */\n font-weight: 600;\n}\n\n/* Focus styles for accessibility */\n*:focus {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\n*:focus:not(:focus-visible) {\n outline: none;\n}\n\n*:focus-visible {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\na {\n color: var(--color-text-primary);\n text-decoration: none;\n transition: color 0.3s ease;\n border-radius: 4px; /* For better focus outline */\n}\na:hover {\n color: var(--color-primary);\n text-decoration: underline;\n}\na:focus {\n color: var(--color-primary);\n}\n\n#components-list a:hover {\n text-decoration: none;\n}\n\np {\n margin-top: 0;\n}\n\n.logo {\n margin-top: 10px;\n}\n\n.back {\n width: 100%;\n margin-top: -20px;\n margin-bottom: 1.5em;\n display: block;\n color: var(--color-text-muted);\n font-size: 0.95em;\n}\n\n/* Content Sections */\n.content-section {\n background: var(--color-bg-card);\n border-radius: 16px;\n border: 1px solid var(--color-border);\n overflow: hidden;\n transition: all 0.3s ease;\n margin-bottom: 2rem;\n}\n\n.content-section:hover {\n border-color: var(--color-border-hover);\n box-shadow: var(--shadow-lg);\n}\n\n.section-header {\n padding: 1.5rem 2rem;\n background: var(--gradient-card);\n border-bottom: 1px solid var(--color-border);\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.section-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--color-text-primary);\n}\n\n.section-icon {\n font-size: 1.25rem;\n /* Removed gradient background, border-radius, and container styling */\n /* Now just using emoji directly for better accessibility */\n}\n\n.section-content {\n padding: 2rem;\n}\n\n.code,\n.preview {\n width: 100%;\n background: var(--color-bg-card);\n border-radius: 16px;\n box-shadow: var(--shadow-md);\n margin-bottom: 1.5em;\n border: 1px solid var(--color-border);\n}\n\n.preview {\n height: 500px;\n}\n\n.preview iframe {\n width: 100%;\n height: 100%;\n border: none;\n background: white;\n border-radius: 0 0 16px 16px;\n}\n\n.table {\n width: 100%;\n}\n\n.w-100 {\n width: 100%;\n}\n\n.row {\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n border-radius: 12px;\n width: 100%;\n display: flex;\n padding: 14px 0px;\n box-sizing: border-box;\n margin-bottom: 8px;\n align-items: center;\n box-shadow: var(--shadow-md);\n transition: all 0.3s ease;\n}\n\n.row.header {\n background: var(--gradient-card);\n border: 1px solid var(--color-border) !important;\n font-size: 1.1em;\n font-weight: 600;\n border-radius: 12px 12px 0 0;\n box-shadow: none;\n color: var(--color-text-primary);\n}\n\n.row.header div {\n font-weight: bold;\n margin: 0;\n align-self: flex-start;\n}\n\n.row.double {\n min-height: 60px;\n}\n\n.row div {\n word-wrap: break-word;\n}\n\n.row span {\n padding-right: 10px;\n}\n\n.componentRow {\n transition:\n box-shadow 0.2s,\n background 0.2s;\n}\n\n.componentRow:hover {\n background: var(--color-bg-glass);\n box-shadow: var(--shadow-lg);\n border-color: var(--color-primary);\n transform: translateY(-2px);\n}\n\n.componentRow .title .name {\n font-weight: bold;\n font-size: 1.15rem;\n margin: 0;\n width: 100%;\n color: var(--color-text-default);\n}\n\n.componentRow .release {\n font-size: 1rem;\n margin: 0;\n width: 100%;\n color: var(--color-text-default);\n}\n\n.componentRow .title .description {\n padding: 0;\n font-size: 0.98rem;\n color: var(--color-text-muted);\n}\n\n.social {\n width: 100%;\n margin-top: 20px;\n text-align: center;\n}\n\n.field {\n width: 100%;\n margin-bottom: 1em;\n}\n\n.field p,\n.field span,\n.field a {\n margin: 0;\n font-weight: 500;\n}\n\n.field p {\n color: var(--color-primary);\n font-weight: bold;\n margin-right: 10px;\n}\n\ninput[type=\"text\"],\ntextarea,\nselect {\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n color: var(--color-text-primary);\n padding: 0.75rem 1rem;\n border-radius: 8px;\n font-family: inherit;\n font-size: 1rem;\n transition: all 0.3s ease;\n margin-bottom: 10px;\n box-sizing: border-box;\n}\n\ninput[type=\"text\"]:focus,\ntextarea:focus,\nselect:focus {\n outline: none;\n border-color: var(--color-primary);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.btn {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n border-radius: 8px;\n font-size: 0.875rem;\n font-weight: 500;\n text-decoration: none;\n transition: all 0.3s ease;\n border: none;\n cursor: pointer;\n font-family: inherit;\n}\n\n.btn-primary {\n background: var(--gradient-primary);\n color: white;\n}\n\n.btn-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--shadow-glow);\n}\n\n.btn-secondary {\n background: var(--color-bg-glass);\n color: var(--color-text-primary);\n border: 1px solid var(--color-border);\n}\n\n.btn-secondary:hover {\n border-color: var(--color-border-hover);\n background: var(--color-bg-secondary);\n}\n\n.filters {\n width: 100%;\n display: flex;\n justify-content: space-between;\n gap: 1em;\n margin-bottom: 0.5em;\n}\n\n.row > * {\n flex: 0 1 8%;\n padding: 0px 5px;\n align-self: center;\n}\n\n.row > *:last-child {\n padding-right: 10px;\n}\n\n.row > *:first-child {\n padding-left: 10px;\n}\n\n.release,\n.title,\n.filters > * {\n flex: 1 0;\n}\n\n.title {\n display: flex;\n flex-direction: column;\n}\n\n.filters input {\n color: #0f0f23;\n background-color: #eee;\n}\n\n#author-filter {\n flex: 0 1 30%;\n}\n\n@media (min-width: 1024px) {\n margin-left: 15px;\n}\n\n.parameter {\n flex: 1 0;\n max-width: 25%;\n align-self: flex-start;\n}\n\n.parameter-description {\n flex: 1 0;\n max-width: 70%;\n}\n\n.author {\n flex: 0 1 15%;\n word-break: break-all;\n color: var(--color-info);\n}\n\n#href {\n height: 60px;\n}\n\n.states {\n width: 100%;\n margin-bottom: 30px;\n display: flex;\n align-items: center;\n gap: 1.5rem;\n flex-wrap: wrap;\n}\n\n.states > span {\n color: var(--color-text-secondary);\n font-weight: 500;\n font-size: 0.875rem;\n}\n\n.states input {\n margin-right: 6px;\n}\n\n/* Custom Checkbox Styling */\n.checkbox-wrapper {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n cursor: pointer;\n user-select: none;\n transition: all 0.3s ease;\n}\n\n.checkbox-wrapper:hover {\n transform: translateY(-1px);\n}\n\n.checkbox-input {\n position: absolute;\n opacity: 0;\n pointer-events: none;\n}\n\n.checkbox-custom {\n position: relative;\n width: 20px;\n height: 20px;\n background: var(--color-bg-card);\n border: 2px solid var(--color-border);\n border-radius: 6px;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.checkbox-input:checked + .checkbox-custom {\n background: var(--gradient-primary);\n border-color: var(--color-primary);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.checkbox-input:focus + .checkbox-custom {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\n.checkbox-icon {\n width: 12px;\n height: 12px;\n stroke: white;\n stroke-width: 2;\n fill: none;\n stroke-linecap: round;\n stroke-linejoin: round;\n opacity: 0;\n transform: scale(0.8);\n transition: all 0.2s ease;\n}\n\n.checkbox-input:checked + .checkbox-custom .checkbox-icon {\n opacity: 1;\n transform: scale(1);\n}\n\n.checkbox-wrapper:hover .checkbox-custom {\n border-color: var(--color-border-hover);\n box-shadow: 0 2px 8px rgba(99, 102, 241, 0.15);\n}\n\n.checkbox-wrapper:hover .checkbox-input:checked + .checkbox-custom {\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2), 0 2px 8px rgba(99, 102, 241, 0.3);\n}\n\n/* Removed old details-state styling - now using state-badge class */\n\n#versions {\n margin-left: 10px;\n}\n\n/* Updated state styling to use modern badge design */\n.state {\n display: inline-flex;\n align-items: center;\n font-size: 0.875rem;\n font-weight: 600;\n padding: 0.375rem 0.75rem;\n border-radius: 12px;\n white-space: nowrap;\n transition: all 0.3s ease;\n border: 1px solid transparent;\n backdrop-filter: blur(10px);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n margin-right: 10px;\n}\n\n.table .state {\n /* Remove the old background and height - now using component-state classes */\n}\n\n/* Enhanced State Badge Styling - moved to component state section */\n\n/* Component State Badge Styling */\n.state-badge {\n display: inline-flex;\n align-items: center;\n font-size: 0.875rem;\n font-weight: 600;\n padding: 0.375rem 0.75rem;\n border-radius: 12px;\n white-space: nowrap;\n transition: all 0.3s ease;\n border: 1px solid transparent;\n backdrop-filter: blur(10px);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n margin-left: 0.75rem;\n}\n\n/* Mobile compact view - hidden on desktop */\n.mobile-compact {\n display: none;\n}\n\n.state-badge:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n/* Experimental state - warm orange/yellow like in the image */\n.component-state-experimental {\n background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);\n color: #92400e;\n border: 1px solid rgba(245, 158, 11, 0.3);\n box-shadow: 0 2px 8px rgba(245, 158, 11, 0.2);\n}\n\n.component-state-experimental:hover {\n box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);\n}\n\n/* Deprecated state - red */\n.component-state-deprecated {\n background: linear-gradient(135deg, #f87171 0%, #ef4444 100%);\n color: #991b1b;\n border: 1px solid rgba(239, 68, 68, 0.3);\n box-shadow: 0 2px 8px rgba(239, 68, 68, 0.2);\n}\n\n.component-state-deprecated:hover {\n box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);\n}\n\n/* Stable state - green */\n.component-state-stable {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: #064e3b;\n border: 1px solid rgba(16, 185, 129, 0.3);\n box-shadow: 0 2px 8px rgba(16, 185, 129, 0.2);\n}\n\n.component-state-stable:hover {\n box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);\n}\n\n/* Beta state - blue */\n.component-state-beta {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: #1e3a8a;\n border: 1px solid rgba(59, 130, 246, 0.3);\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.2);\n}\n\n.component-state-beta:hover {\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);\n}\n\n/* Alpha state - purple */\n.component-state-alpha {\n background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n color: #4c1d95;\n border: 1px solid rgba(139, 92, 246, 0.3);\n box-shadow: 0 2px 8px rgba(139, 92, 246, 0.2);\n}\n\n.component-state-alpha:hover {\n box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);\n}\n\na.tab-link {\n color: var(--color-primary-light);\n font-weight: 500;\n padding: 0.5rem 1rem;\n border-radius: 8px;\n transition: all 0.3s ease;\n font-size: 1rem;\n line-height: 1.2;\n vertical-align: middle;\n display: inline-block;\n border: 1px solid transparent;\n}\n\na.tab-link:hover {\n background: var(--color-bg-glass);\n border-color: var(--color-border);\n}\n\na.tab-link.selected {\n background: var(--gradient-primary);\n color: white;\n text-decoration: none;\n border-color: var(--color-primary);\n}\n\n.bold {\n font-weight: bold;\n}\n\n.hide {\n display: none !important;\n}\n\n.box {\n background: var(--color-bg-card);\n border-radius: 12px; /* Reduced from 16px */\n border: 1px solid var(--color-border);\n padding: 1.5em 2em;\n margin-bottom: 2em;\n transition: all 0.3s ease;\n /* Removed default shadow */\n}\n\n.box:hover {\n border-color: var(--color-border-hover);\n box-shadow: var(--shadow-md); /* Only on hover */\n transform: translateY(-1px); /* Reduced from -2px */\n}\n\n/* Hero Section */\n.hero {\n padding: 3rem 0;\n text-align: center;\n position: relative;\n}\n\n/* Info Cards */\n.info-card {\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n border-radius: 12px; /* Reduced from 16px */\n padding: 1.5rem;\n transition: all 0.3s ease;\n margin-bottom: 1.5rem;\n /* Removed default shadow */\n}\n\n.info-card:hover {\n border-color: var(--color-border-hover);\n transform: translateY(-1px); /* Reduced from -2px */\n box-shadow: var(--shadow-md); /* Reduced from shadow-lg */\n}\n\n.info-item {\n display: flow;\n align-items: start;\n padding: 0.75rem 0;\n border-bottom: 1px solid var(--color-border);\n}\n\n.info-item:last-child {\n border-bottom: none;\n}\n\n.info-label {\n font-weight: 500;\n color: var(--color-text-secondary);\n min-width: 100px;\n}\n\n.info-value {\n color: var(--color-text-primary);\n text-align: right;\n flex: 1;\n margin-left: 1rem;\n}\n\n/* Animations */\n@keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(30px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes float {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-10px); }\n}\n\n/* Custom scrollbar */\n::-webkit-scrollbar {\n width: 8px;\n}\n\n::-webkit-scrollbar-track {\n background: var(--color-bg-secondary);\n}\n\n::-webkit-scrollbar-thumb {\n background: var(--gradient-primary);\n border-radius: 4px;\n}\n\n::-webkit-scrollbar-thumb:hover {\n background: var(--gradient-secondary);\n}\n\n/* Main Content Layout */\n.main-content {\n display: grid;\n grid-template-columns: 1fr 350px;\n gap: 2rem;\n padding: 2rem 0;\n}\n\n.sidebar {\n display: grid;\n gap: 1.5rem;\n align-content: start;\n}\n\n/* Collapsible Sections */\n.collapsible-section {\n transition: all 0.3s ease;\n}\n\n.collapsible-header {\n cursor: pointer;\n user-select: none;\n position: relative;\n transition: all 0.3s ease;\n}\n\n.collapsible-header:hover {\n background: var(--color-bg-glass);\n}\n\n.collapse-toggle {\n position: absolute;\n right: 1.5rem;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n color: var(--color-text-secondary);\n font-size: 1rem;\n cursor: pointer;\n padding: 0.5rem;\n border-radius: 4px;\n transition: all 0.3s ease;\n}\n\n.collapse-toggle:hover {\n background: var(--color-bg-glass);\n color: var(--color-text-primary);\n}\n\n.collapse-icon {\n transition: transform 0.3s ease;\n display: inline-block;\n}\n\n.collapsible-content {\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.collapsible-content.collapsed {\n max-height: 0;\n padding-top: 0;\n padding-bottom: 0;\n opacity: 0;\n}\n\n.collapsible-content.expanded {\n max-height: 2000px;\n opacity: 1;\n}\n\n.collapsible-header.collapsed .collapse-icon {\n transform: rotate(-90deg);\n}\n\n/* Responsive */\n@media (max-width: 1024px) {\n\n .info-item {\n display: flex;\n justify-content: space-between;\n }\n\n .container {\n padding: 0 1rem;\n }\n\n h1 {\n font-size: 2.5rem;\n }\n\n .main-content {\n grid-template-columns: 1fr;\n gap: 1.5rem;\n }\n\n .sidebar {\n order: -1;\n }\n\n /* Mobile collapsible sections - collapsed by default */\n .collapsible-content {\n max-height: 0;\n padding-top: 0;\n padding-bottom: 0;\n opacity: 0;\n }\n\n .collapsible-header.collapsed .collapse-icon {\n transform: rotate(-90deg);\n }\n}\n\n@media (max-width: 900px) {\n .container {\n padding: 0 1rem;\n }\n\n .main-content {\n padding: 1rem 0;\n gap: 1rem;\n }\n\n .filters {\n flex-direction: column;\n gap: 0.5em;\n }\n\n /* Mobile responsive components list */\n .row.header {\n display: none; /* Hide desktop table header on mobile */\n }\n\n .componentRow {\n flex-direction: column !important;\n align-items: center !important;\n padding: 1rem !important;\n gap: 0.75rem !important;\n text-align: center !important;\n }\n\n /* Hide desktop table columns on mobile */\n .componentRow > .author,\n .componentRow > .date,\n .componentRow > .activity,\n .componentRow > div:not(.title):not(.state):not(.mobile-compact) {\n display: none !important;\n }\n\n /* Show mobile compact view */\n .mobile-compact {\n display: block !important;\n width: 100%;\n }\n\n .mobile-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 0.75rem;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n color: var(--color-text-secondary);\n width: 100%;\n }\n\n .mobile-meta span {\n background: var(--color-bg-glass);\n padding: 0.25rem 0.5rem;\n border-radius: 6px;\n border: 1px solid var(--color-border);\n font-size: 0.8rem;\n font-weight: 500;\n }\n\n .mobile-author {\n color: var(--color-primary) !important;\n }\n\n .mobile-version {\n color: var(--color-text-primary) !important;\n font-weight: 600;\n }\n\n .mobile-date {\n color: var(--color-text-muted) !important;\n }\n\n .mobile-activity {\n color: var(--color-accent) !important;\n }\n\n .mobile-size {\n color: var(--color-secondary) !important;\n }\n\n /* Center the title section on mobile */\n .componentRow .title {\n text-align: center !important;\n width: 100%;\n }\n\n .componentRow .title .name {\n text-align: center !important;\n }\n\n .componentRow .title .description {\n text-align: center !important;\n }\n\n .box, .info-card, .section-content {\n padding: 1.5rem 1rem;\n }\n\n .sidebar .info-card {\n padding: 1rem;\n }\n\n .sidebar .info-item {\n flex-direction: column;\n align-items: flex-start;\n gap: 0.5rem;\n }\n\n .sidebar .info-label {\n min-width: auto;\n font-weight: 600;\n }\n\n .sidebar .info-value {\n text-align: left;\n margin-left: 0;\n }\n\n h1 {\n font-size: 2rem;\n }\n}\n\n/* Loading states */\n.loader {\n text-align: center;\n padding: 2em;\n color: var(--color-text-muted);\n}\n\n.loader p {\n margin: 0;\n font-style: italic;\n}\n\n.loader::before {\n content: '';\n display: inline-block;\n width: 20px;\n height: 20px;\n border: 2px solid var(--color-border);\n border-top: 2px solid var(--color-primary);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-right: 0.5em;\n vertical-align: middle;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.loading-more {\n text-align: center;\n padding: 1em 2em;\n color: var(--color-text-muted);\n font-style: italic;\n font-size: 0.9em;\n border-top: 1px solid var(--color-border);\n margin-top: 1em;\n}\n\n.loading-more::before {\n content: '';\n display: inline-block;\n width: 16px;\n height: 16px;\n border: 2px solid var(--color-border);\n border-top: 2px solid var(--color-primary);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-right: 0.5em;\n vertical-align: middle;\n}\n\n#history-error {\n text-align: center;\n padding: 2em;\n color: var(--color-danger-text);\n background-color: var(--color-danger);\n border: 1px solid var(--color-state-border);\n border-radius: 6px;\n margin: 1em 0;\n}\n\n#history-error p {\n margin: 0;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n color: var(--color-text-secondary);\n font-size: 0.875rem;\n}\n\n.breadcrumb a {\n color: var(--color-primary-light);\n text-decoration: none;\n transition: color 0.3s ease;\n}\n\n.breadcrumb a:hover {\n color: var(--color-primary);\n}\n\n/* Parameters */\n.parameter-grid {\n display: grid;\n gap: 1.5rem;\n}\n\n.parameter-item {\n background: var(--color-bg-glass);\n border: 1px solid var(--color-border);\n border-radius: 12px;\n padding: 1.5rem;\n transition: all 0.3s ease;\n}\n\n.parameter-item:hover {\n border-color: var(--color-primary);\n box-shadow: 0 0 20px rgba(99, 102, 241, 0.1);\n}\n\n.parameter-header {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 1rem;\n}\n\n.parameter-name {\n font-weight: 600;\n color: var(--color-text-primary);\n}\n\n.parameter-type {\n background: var(--color-secondary);\n color: white;\n padding: 0.25rem 0.75rem;\n border-radius: 12px; /* Reduced from 20px */\n font-size: 0.75rem;\n font-weight: 500;\n}\n\n.parameter-required {\n background: var(--color-accent);\n}\n\n.parameter-description {\n color: var(--color-text-secondary);\n margin-bottom: 1rem;\n line-height: 1.5;\n}\n\n.parameter-input {\n width: 100%;\n background: var(--color-bg-secondary);\n border: 1px solid var(--color-border);\n color: var(--color-text-primary);\n padding: 0.75rem 1rem;\n border-radius: 8px;\n font-family: inherit;\n transition: all 0.3s ease;\n}\n\n.parameter-input:focus {\n outline: none;\n border-color: var(--color-primary);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n/* Preview Section */\n.preview-section {\n background: var(--color-bg-card);\n border-radius: 16px;\n border: 1px solid var(--color-border);\n overflow: hidden;\n margin-top: 2rem;\n}\n\n.preview-controls {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 2rem;\n background: var(--color-bg-glass);\n border-bottom: 1px solid var(--color-border);\n}\n\n.preview-buttons {\n display: flex;\n gap: 0.75rem;\n}\n\n.preview-iframe {\n width: 100%;\n height: 500px;\n border: none;\n background: white;\n}\n\n.back {\n width: 100%;\n margin-top: -20px;\n margin-bottom: 1.5em;\n display: block;\n color: var(--color-text-muted);\n font-size: 0.95em;\n}\n\n/* Stats Badge */\n.stats-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n border-radius: 12px;\n padding: 0.75rem 1.25rem;\n margin: 1.5rem auto 0;\n box-shadow: var(--shadow-md);\n transition: all 0.3s ease;\n max-width: fit-content;\n}\n\n.stats-badge:hover {\n border-color: var(--color-border-hover);\n box-shadow: var(--shadow-lg);\n transform: translateY(-1px);\n}\n\n.stats-badge .chart-icon {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.stats-badge .chart-bar {\n width: 4px;\n border-radius: 2px;\n background: var(--gradient-primary);\n}\n\n.stats-badge .chart-bar:nth-child(1) {\n height: 12px;\n background: #10b981; /* green */\n}\n\n.stats-badge .chart-bar:nth-child(2) {\n height: 16px;\n background: #ef4444; /* red */\n}\n\n.stats-badge .chart-bar:nth-child(3) {\n height: 20px;\n background: #3b82f6; /* blue */\n}\n\n.stats-badge .badge-text {\n color: var(--color-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n white-space: nowrap;\n}\n ";
1
+ declare const _default: "\n@import url(\"https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap\");\n\n:root {\n /* Primary brand colors (consistent across themes) */\n --color-primary: #6366f1;\n --color-primary-dark: #4f46e5;\n --color-primary-light: #818cf8;\n --color-secondary: #06b6d4;\n --color-accent: #f59e0b;\n\n --gradient-primary: linear-gradient(135deg, #6366f1 0%, #8b5cf6 100%);\n --gradient-secondary: linear-gradient(135deg, #06b6d4 0%, #0891b2 100%);\n --gradient-accent: linear-gradient(135deg, #f59e0b 0%, #d97706 100%);\n\n /* Legacy color mappings for backward compatibility */\n --color-warning: #ffe066;\n --color-warning-text: #7c3aed;\n --color-danger: #ffd6d6;\n --color-danger-text: #c92a2a;\n --color-state-border: #e9ecef;\n}\n\n/* Dark theme (default) */\n:root, [data-theme=\"dark\"] {\n --color-bg-primary: #0f0f23;\n --color-bg-secondary: #1a1a2e;\n --color-bg-card: #16213e;\n --color-bg-glass: rgba(255, 255, 255, 0.05);\n\n --color-text-primary: #ffffff;\n --color-text-secondary: #b4b4b8;\n --color-text-muted: #acacb9;\n\n --color-border: rgba(255, 255, 255, 0.1);\n --color-border-hover: rgba(255, 255, 255, 0.2);\n\n --gradient-card: rgba(255,255,255,0.03); /* Simplified from gradient */\n\n --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n --shadow-glow: 0 0 20px rgba(99, 102, 241, 0.3);\n\n /* Dark theme text inverse (for buttons, etc) */\n --color-text-inverse: #ffffff;\n}\n\n/* Light theme */\n[data-theme=\"light\"] {\n --color-bg-primary: #ffffff;\n --color-bg-secondary: #f8fafc;\n --color-bg-card: #ffffff;\n --color-bg-glass: rgba(255, 255, 255, 0.8);\n\n --color-text-primary: #1e293b;\n --color-text-secondary: #475569; /* Improved contrast from #64748b */\n --color-text-muted: #64748b; /* Improved contrast from #94a3b8 */\n\n --color-border: rgba(0, 0, 0, 0.1);\n --color-border-hover: rgba(0, 0, 0, 0.15);\n\n --gradient-card: rgba(0,0,0,0.02); /* Simplified from gradient */\n\n --shadow-sm: 0 1px 2px 0 rgba(0, 0, 0, 0.05);\n --shadow-md: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06);\n --shadow-lg: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);\n --shadow-xl: 0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04);\n --shadow-glow: 0 0 20px rgba(99, 102, 241, 0.2);\n\n /* Light theme text inverse (for buttons, etc) */\n --color-text-inverse: #ffffff;\n}\n\n* {\n margin: 0;\n padding: 0;\n box-sizing: border-box;\n}\n\n@media (prefers-reduced-motion: no-preference) {\n @view-transition {\n navigation: auto;\n }\n}\n\nbody {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n background: var(--color-bg-primary);\n color: var(--color-text-primary);\n line-height: 1.6;\n min-height: 100vh;\n overflow-x: hidden;\n}\n\n/* Animated background - Dark theme */\nbody::before {\n content: '';\n position: fixed;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n background:\n radial-gradient(circle at 20% 80%, rgba(99, 102, 241, 0.1) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(139, 92, 246, 0.1) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(6, 182, 212, 0.05) 0%, transparent 50%);\n z-index: -1;\n transition: opacity 0.3s ease;\n}\n\n/* Animated background - Light theme */\n[data-theme=\"light\"] body::before {\n background:\n radial-gradient(circle at 20% 80%, rgba(99, 102, 241, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 80% 20%, rgba(139, 92, 246, 0.03) 0%, transparent 50%),\n radial-gradient(circle at 40% 40%, rgba(6, 182, 212, 0.02) 0%, transparent 50%);\n}\n\n.container {\n max-width: 1400px;\n margin: 0 auto;\n padding: 0 2rem;\n}\n\n/* Header */\n.header {\n background: var(--color-bg-glass);\n backdrop-filter: blur(20px);\n border-bottom: 1px solid var(--color-border);\n position: sticky;\n top: 0;\n z-index: 100;\n}\n\n.header-content {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 0;\n}\n\n.logo {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n text-decoration: none;\n color: var(--color-text-primary);\n font-weight: 700;\n font-size: 1.25rem;\n transition: all 0.3s ease;\n}\n\n.logo:hover {\n color: var(--color-primary-light);\n transform: translateY(-1px);\n}\n\n.logo-icon {\n color: #fff;\n width: 32px;\n height: 32px;\n background: var(--gradient-primary);\n border-radius: 8px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: bold;\n font-size: 1.1rem;\n}\n\n.logo img {\n width: 32px;\n height: 32px;\n border-radius: 8px;\n}\n\n/* Theme Toggle Button */\n.theme-toggle {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n background: var(--color-bg-glass);\n border: 1px solid var(--color-border);\n border-radius: 8px;\n color: var(--color-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n transition: all 0.3s ease;\n cursor: pointer;\n backdrop-filter: blur(10px);\n}\n\n.theme-toggle:hover {\n border-color: var(--color-border-hover);\n background: var(--color-bg-card);\n transform: translateY(-1px);\n}\n\n.theme-toggle-icon {\n font-size: 1.1rem;\n transition: transform 0.3s ease;\n}\n\n.theme-toggle:hover .theme-toggle-icon {\n transform: rotate(15deg);\n}\n\nh1, h2, h3 {\n color: var(--color-text-primary);\n font-weight: 600;\n margin-bottom: 0.5em;\n}\n\nh1 {\n font-size: 3.5rem;\n font-weight: 700;\n background: var(--gradient-primary);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n background-clip: text;\n margin-bottom: 1rem;\n text-align: center;\n}\n\nh2 {\n font-size: 1.5rem; /* Increased from 1.25rem */\n font-weight: 600;\n color: var(--color-text-primary);\n margin-bottom: 0.75em;\n}\n\nh3 {\n font-size: 1.25rem; /* Increased from 1.1rem */\n font-weight: 600;\n}\n\n/* Focus styles for accessibility */\n*:focus {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\n*:focus:not(:focus-visible) {\n outline: none;\n}\n\n*:focus-visible {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\na {\n color: var(--color-text-primary);\n text-decoration: none;\n transition: color 0.3s ease;\n border-radius: 4px; /* For better focus outline */\n}\na:hover {\n color: var(--color-primary);\n text-decoration: underline;\n}\na:focus {\n color: var(--color-primary);\n}\n\n#components-list a:hover {\n text-decoration: none;\n}\n\np {\n margin-top: 0;\n}\n\n.logo {\n margin-top: 10px;\n}\n\n.back {\n width: 100%;\n margin-top: -20px;\n margin-bottom: 1.5em;\n display: block;\n color: var(--color-text-muted);\n font-size: 0.95em;\n}\n\n/* Content Sections */\n.content-section {\n background: var(--color-bg-card);\n border-radius: 16px;\n border: 1px solid var(--color-border);\n overflow: hidden;\n transition: all 0.3s ease;\n margin-bottom: 2rem;\n}\n\n.content-section:hover {\n border-color: var(--color-border-hover);\n box-shadow: var(--shadow-lg);\n}\n\n.section-header {\n padding: 1.5rem 2rem;\n background: var(--gradient-card);\n border-bottom: 1px solid var(--color-border);\n display: flex;\n align-items: center;\n gap: 0.75rem;\n}\n\n.section-title {\n font-size: 1.25rem;\n font-weight: 600;\n color: var(--color-text-primary);\n}\n\n.section-icon {\n font-size: 1.25rem;\n /* Removed gradient background, border-radius, and container styling */\n /* Now just using emoji directly for better accessibility */\n}\n\n.section-content {\n padding: 2rem;\n}\n\n.code,\n.preview {\n width: 100%;\n background: var(--color-bg-card);\n border-radius: 16px;\n box-shadow: var(--shadow-md);\n margin-bottom: 1.5em;\n border: 1px solid var(--color-border);\n}\n\n.preview {\n height: 500px;\n}\n\n.preview iframe {\n width: 100%;\n height: 100%;\n border: none;\n background: white;\n border-radius: 0 0 16px 16px;\n}\n\n.table {\n width: 100%;\n}\n\n.w-100 {\n width: 100%;\n}\n\n.row {\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n border-radius: 12px;\n width: 100%;\n display: flex;\n padding: 14px 0px;\n box-sizing: border-box;\n margin-bottom: 8px;\n align-items: center;\n box-shadow: var(--shadow-md);\n transition: all 0.3s ease;\n}\n\n.row.header {\n background: var(--gradient-card);\n border: 1px solid var(--color-border) !important;\n font-size: 1.1em;\n font-weight: 600;\n border-radius: 12px 12px 0 0;\n box-shadow: none;\n color: var(--color-text-primary);\n}\n\n.row.header div {\n font-weight: bold;\n margin: 0;\n align-self: flex-start;\n}\n\n.row.double {\n min-height: 60px;\n}\n\n.row div {\n word-wrap: break-word;\n}\n\n.row span {\n padding-right: 10px;\n}\n\n.componentRow {\n transition:\n box-shadow 0.2s,\n background 0.2s;\n}\n\n.componentRow:hover {\n background: var(--color-bg-glass);\n box-shadow: var(--shadow-lg);\n border-color: var(--color-primary);\n transform: translateY(-2px);\n}\n\n.componentRow .title .name {\n font-weight: bold;\n font-size: 1.15rem;\n margin: 0;\n width: 100%;\n color: var(--color-text-primary);\n}\n\n.componentRow .release {\n font-size: 1rem;\n margin: 0;\n width: 100%;\n color: var(--color-text-primary);\n}\n\n.componentRow .title .description {\n padding: 0;\n font-size: 0.98rem;\n color: var(--color-text-muted);\n}\n\n.social {\n width: 100%;\n margin-top: 20px;\n text-align: center;\n}\n\n.field {\n width: 100%;\n margin-bottom: 1em;\n}\n\n.field p,\n.field span,\n.field a {\n margin: 0;\n font-weight: 500;\n}\n\n.field p {\n color: var(--color-primary);\n font-weight: bold;\n margin-right: 10px;\n}\n\ninput[type=\"text\"],\ntextarea,\nselect {\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n color: var(--color-text-primary);\n padding: 0.75rem 1rem;\n border-radius: 8px;\n font-family: inherit;\n font-size: 1rem;\n transition: all 0.3s ease;\n margin-bottom: 10px;\n box-sizing: border-box;\n}\n\ninput[type=\"text\"]:focus,\ntextarea:focus,\nselect:focus {\n outline: none;\n border-color: var(--color-primary);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.btn {\n display: inline-flex;\n align-items: center;\n gap: 0.5rem;\n padding: 0.5rem 1rem;\n border-radius: 8px;\n font-size: 0.875rem;\n font-weight: 500;\n text-decoration: none;\n transition: all 0.3s ease;\n border: none;\n cursor: pointer;\n font-family: inherit;\n}\n\n.btn-primary {\n background: var(--gradient-primary);\n color: white;\n}\n\n.btn-primary:hover {\n transform: translateY(-1px);\n box-shadow: var(--shadow-glow);\n}\n\n.btn-secondary {\n background: var(--color-bg-glass);\n color: var(--color-text-primary);\n border: 1px solid var(--color-border);\n}\n\n.btn-secondary:hover {\n border-color: var(--color-border-hover);\n background: var(--color-bg-secondary);\n}\n\n.filters {\n width: 100%;\n display: flex;\n justify-content: space-between;\n gap: 1em;\n margin-bottom: 0.5em;\n}\n\n.row > * {\n flex: 0 1 8%;\n padding: 0px 5px;\n align-self: center;\n}\n\n.row > *:last-child {\n padding-right: 10px;\n}\n\n.row > *:first-child {\n padding-left: 10px;\n}\n\n.release,\n.title,\n.filters > * {\n flex: 1 0;\n}\n\n.title {\n display: flex;\n flex-direction: column;\n}\n\n.filters input {\n color: var(--color-text-primary);\n background-color: var(--color-bg-card);\n}\n\n#author-filter {\n flex: 0 1 30%;\n}\n\n.parameter {\n flex: 1 0;\n max-width: 25%;\n align-self: flex-start;\n}\n\n.parameter-description {\n flex: 1 0;\n max-width: 70%;\n}\n\n.author {\n flex: 0 1 15%;\n word-break: break-all;\n color: var(--color-text-secondary);\n}\n\n#href {\n height: 60px;\n}\n\n.states {\n width: 100%;\n margin-bottom: 30px;\n display: flex;\n align-items: center;\n gap: 1.5rem;\n flex-wrap: wrap;\n}\n\n.states > span {\n color: var(--color-text-secondary);\n font-weight: 500;\n font-size: 0.875rem;\n}\n\n.states input {\n margin-right: 6px;\n}\n\n/* Custom Checkbox Styling */\n.checkbox-wrapper {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n cursor: pointer;\n user-select: none;\n transition: all 0.3s ease;\n}\n\n.checkbox-wrapper:hover {\n transform: translateY(-1px);\n}\n\n.checkbox-input {\n position: absolute;\n opacity: 0;\n pointer-events: none;\n}\n\n.checkbox-custom {\n position: relative;\n width: 20px;\n height: 20px;\n background: var(--color-bg-card);\n border: 2px solid var(--color-border);\n border-radius: 6px;\n transition: all 0.3s ease;\n display: flex;\n align-items: center;\n justify-content: center;\n flex-shrink: 0;\n}\n\n.checkbox-input:checked + .checkbox-custom {\n background: var(--gradient-primary);\n border-color: var(--color-primary);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n.checkbox-input:focus + .checkbox-custom {\n outline: 2px solid var(--color-primary);\n outline-offset: 2px;\n}\n\n.checkbox-icon {\n width: 12px;\n height: 12px;\n stroke: white;\n stroke-width: 2;\n fill: none;\n stroke-linecap: round;\n stroke-linejoin: round;\n opacity: 0;\n transform: scale(0.8);\n transition: all 0.2s ease;\n}\n\n.checkbox-input:checked + .checkbox-custom .checkbox-icon {\n opacity: 1;\n transform: scale(1);\n}\n\n.checkbox-wrapper:hover .checkbox-custom {\n border-color: var(--color-border-hover);\n box-shadow: 0 2px 8px rgba(99, 102, 241, 0.15);\n}\n\n.checkbox-wrapper:hover .checkbox-input:checked + .checkbox-custom {\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.2), 0 2px 8px rgba(99, 102, 241, 0.3);\n}\n\n/* Removed old details-state styling - now using state-badge class */\n\n#versions {\n margin-left: 10px;\n}\n\n/* Updated state styling to use modern badge design */\n.state {\n display: inline-flex;\n align-items: center;\n font-size: 0.875rem;\n font-weight: 600;\n padding: 0.375rem 0.75rem;\n border-radius: 12px;\n white-space: nowrap;\n transition: all 0.3s ease;\n border: 1px solid transparent;\n backdrop-filter: blur(10px);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n margin-right: 10px;\n}\n\n.table .state {\n /* Remove the old background and height - now using component-state classes */\n}\n\n/* Enhanced State Badge Styling - moved to component state section */\n\n/* Component State Badge Styling */\n.state-badge {\n display: inline-flex;\n align-items: center;\n font-size: 0.875rem;\n font-weight: 600;\n padding: 0.375rem 0.75rem;\n border-radius: 12px;\n white-space: nowrap;\n transition: all 0.3s ease;\n border: 1px solid transparent;\n backdrop-filter: blur(10px);\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n margin-left: 0.75rem;\n}\n\n/* Mobile compact view - hidden on desktop */\n.mobile-compact {\n display: none;\n}\n\n.state-badge:hover {\n transform: translateY(-1px);\n box-shadow: 0 4px 12px rgba(0, 0, 0, 0.15);\n}\n\n/* Experimental state - warm orange/yellow like in the image */\n.component-state-experimental {\n background: linear-gradient(135deg, #fbbf24 0%, #f59e0b 100%);\n color: #92400e;\n border: 1px solid rgba(245, 158, 11, 0.3);\n box-shadow: 0 2px 8px rgba(245, 158, 11, 0.2);\n}\n\n.component-state-experimental:hover {\n box-shadow: 0 4px 12px rgba(245, 158, 11, 0.3);\n}\n\n/* Deprecated state - red */\n.component-state-deprecated {\n background: linear-gradient(135deg, #f87171 0%, #ef4444 100%);\n color: #991b1b;\n border: 1px solid rgba(239, 68, 68, 0.3);\n box-shadow: 0 2px 8px rgba(239, 68, 68, 0.2);\n}\n\n.component-state-deprecated:hover {\n box-shadow: 0 4px 12px rgba(239, 68, 68, 0.3);\n}\n\n/* Stable state - green */\n.component-state-stable {\n background: linear-gradient(135deg, #10b981 0%, #059669 100%);\n color: #064e3b;\n border: 1px solid rgba(16, 185, 129, 0.3);\n box-shadow: 0 2px 8px rgba(16, 185, 129, 0.2);\n}\n\n.component-state-stable:hover {\n box-shadow: 0 4px 12px rgba(16, 185, 129, 0.3);\n}\n\n/* Beta state - blue */\n.component-state-beta {\n background: linear-gradient(135deg, #3b82f6 0%, #2563eb 100%);\n color: #1e3a8a;\n border: 1px solid rgba(59, 130, 246, 0.3);\n box-shadow: 0 2px 8px rgba(59, 130, 246, 0.2);\n}\n\n.component-state-beta:hover {\n box-shadow: 0 4px 12px rgba(59, 130, 246, 0.3);\n}\n\n/* Alpha state - purple */\n.component-state-alpha {\n background: linear-gradient(135deg, #8b5cf6 0%, #7c3aed 100%);\n color: #4c1d95;\n border: 1px solid rgba(139, 92, 246, 0.3);\n box-shadow: 0 2px 8px rgba(139, 92, 246, 0.2);\n}\n\n.component-state-alpha:hover {\n box-shadow: 0 4px 12px rgba(139, 92, 246, 0.3);\n}\n\na.tab-link {\n color: var(--color-primary-light);\n font-weight: 500;\n padding: 0.5rem 1rem;\n border-radius: 8px;\n transition: all 0.3s ease;\n font-size: 1rem;\n line-height: 1.2;\n vertical-align: middle;\n display: inline-block;\n border: 1px solid transparent;\n}\n\na.tab-link:hover {\n background: var(--color-bg-glass);\n border-color: var(--color-border);\n}\n\na.tab-link.selected {\n background: var(--gradient-primary);\n color: white;\n text-decoration: none;\n border-color: var(--color-primary);\n}\n\n.bold {\n font-weight: bold;\n}\n\n.hide {\n display: none !important;\n}\n\n.box {\n background: var(--color-bg-card);\n border-radius: 12px; /* Reduced from 16px */\n border: 1px solid var(--color-border);\n padding: 1.5em 2em;\n margin-bottom: 2em;\n transition: all 0.3s ease;\n /* Removed default shadow */\n}\n\n.box:hover {\n border-color: var(--color-border-hover);\n box-shadow: var(--shadow-md); /* Only on hover */\n transform: translateY(-1px); /* Reduced from -2px */\n}\n\n/* Hero Section */\n.hero {\n padding: 3rem 0;\n text-align: center;\n position: relative;\n}\n\n/* Info Cards */\n.info-card {\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n border-radius: 12px; /* Reduced from 16px */\n padding: 1.5rem;\n transition: all 0.3s ease;\n margin-bottom: 1.5rem;\n /* Removed default shadow */\n}\n\n.info-card:hover {\n border-color: var(--color-border-hover);\n transform: translateY(-1px); /* Reduced from -2px */\n box-shadow: var(--shadow-md); /* Reduced from shadow-lg */\n}\n\n.info-item {\n display: flex;\n align-items: start;\n padding: 0.75rem 0;\n border-bottom: 1px solid var(--color-border);\n}\n\n.info-item:last-child {\n border-bottom: none;\n}\n\n.info-label {\n font-weight: 500;\n color: var(--color-text-secondary);\n min-width: 100px;\n}\n\n.info-value {\n color: var(--color-text-primary);\n text-align: right;\n flex: 1;\n margin-left: 1rem;\n}\n\n/* Animations */\n@keyframes fadeInUp {\n from {\n opacity: 0;\n transform: translateY(30px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n@keyframes float {\n 0%, 100% { transform: translateY(0px); }\n 50% { transform: translateY(-10px); }\n}\n\n/* Custom scrollbar */\n::-webkit-scrollbar {\n width: 8px;\n}\n\n::-webkit-scrollbar-track {\n background: var(--color-bg-secondary);\n}\n\n::-webkit-scrollbar-thumb {\n background: var(--color-border-hover);\n border-radius: 4px;\n}\n\n::-webkit-scrollbar-thumb:hover {\n background: var(--color-primary);\n}\n\n/* Main Content Layout */\n.main-content {\n display: grid;\n grid-template-columns: 1fr 350px;\n gap: 2rem;\n padding: 2rem 0;\n}\n\n.sidebar {\n display: grid;\n gap: 1.5rem;\n align-content: start;\n}\n\n/* Collapsible Sections */\n.collapsible-section {\n transition: all 0.3s ease;\n}\n\n.collapsible-header {\n cursor: pointer;\n user-select: none;\n position: relative;\n transition: all 0.3s ease;\n}\n\n.collapsible-header:hover {\n background: var(--color-bg-glass);\n}\n\n.collapse-toggle {\n position: absolute;\n right: 1.5rem;\n top: 50%;\n transform: translateY(-50%);\n background: none;\n border: none;\n color: var(--color-text-secondary);\n font-size: 1rem;\n cursor: pointer;\n padding: 0.5rem;\n border-radius: 4px;\n transition: all 0.3s ease;\n}\n\n.collapse-toggle:hover {\n background: var(--color-bg-glass);\n color: var(--color-text-primary);\n}\n\n.collapse-icon {\n transition: transform 0.3s ease;\n display: inline-block;\n}\n\n.collapsible-content {\n overflow: hidden;\n transition: all 0.3s ease;\n}\n\n.collapsible-content.collapsed {\n max-height: 0;\n padding-top: 0;\n padding-bottom: 0;\n opacity: 0;\n}\n\n.collapsible-content.expanded {\n max-height: 2000px;\n opacity: 1;\n}\n\n.collapsible-header.collapsed .collapse-icon {\n transform: rotate(-90deg);\n}\n\n/* Responsive */\n@media (max-width: 1024px) {\n\n .info-item {\n display: flex;\n justify-content: space-between;\n }\n\n .container {\n padding: 0 1rem;\n }\n\n h1 {\n font-size: 2.5rem;\n }\n\n .main-content {\n grid-template-columns: 1fr;\n gap: 1.5rem;\n }\n\n .sidebar {\n order: -1;\n }\n\n /* Mobile collapsible sections - collapsed by default */\n .collapsible-content {\n max-height: 0;\n padding-top: 0;\n padding-bottom: 0;\n opacity: 0;\n }\n\n .collapsible-header.collapsed .collapse-icon {\n transform: rotate(-90deg);\n }\n}\n\n@media (max-width: 900px) {\n .container {\n padding: 0 1rem;\n }\n\n .main-content {\n padding: 1rem 0;\n gap: 1rem;\n }\n\n .filters {\n flex-direction: column;\n gap: 0.5em;\n }\n\n /* Mobile responsive components list */\n .row.header {\n display: none; /* Hide desktop table header on mobile */\n }\n\n .componentRow {\n flex-direction: column !important;\n align-items: center !important;\n padding: 1rem !important;\n gap: 0.75rem !important;\n text-align: center !important;\n }\n\n /* Hide desktop table columns on mobile */\n .componentRow > .author,\n .componentRow > .date,\n .componentRow > .activity,\n .componentRow > div:not(.title):not(.state):not(.mobile-compact) {\n display: none !important;\n }\n\n /* Show mobile compact view */\n .mobile-compact {\n display: block !important;\n width: 100%;\n }\n\n .mobile-meta {\n display: flex;\n flex-wrap: wrap;\n gap: 0.75rem;\n align-items: center;\n justify-content: center;\n font-size: 0.875rem;\n color: var(--color-text-secondary);\n width: 100%;\n }\n\n .mobile-meta span {\n background: var(--color-bg-glass);\n padding: 0.25rem 0.5rem;\n border-radius: 6px;\n border: 1px solid var(--color-border);\n font-size: 0.8rem;\n font-weight: 500;\n }\n\n .mobile-author {\n color: var(--color-primary) !important;\n }\n\n .mobile-version {\n color: var(--color-text-primary) !important;\n font-weight: 600;\n }\n\n .mobile-date {\n color: var(--color-text-muted) !important;\n }\n\n .mobile-activity {\n color: var(--color-accent) !important;\n }\n\n .mobile-size {\n color: var(--color-secondary) !important;\n }\n\n /* Center the title section on mobile */\n .componentRow .title {\n text-align: center !important;\n width: 100%;\n }\n\n .componentRow .title .name {\n text-align: center !important;\n }\n\n .componentRow .title .description {\n text-align: center !important;\n }\n\n .box, .info-card, .section-content {\n padding: 1.5rem 1rem;\n }\n\n .sidebar .info-card {\n padding: 1rem;\n }\n\n .sidebar .info-item {\n flex-direction: column;\n align-items: flex-start;\n gap: 0.5rem;\n }\n\n .sidebar .info-label {\n min-width: auto;\n font-weight: 600;\n }\n\n .sidebar .info-value {\n text-align: left;\n margin-left: 0;\n }\n\n h1 {\n font-size: 2rem;\n }\n}\n\n/* Loading states */\n.loader {\n text-align: center;\n padding: 2em;\n color: var(--color-text-muted);\n}\n\n.empty-state {\n text-align: center;\n padding: 2em;\n color: var(--color-text-muted);\n font-style: italic;\n margin: 0;\n}\n\n.loader p {\n margin: 0;\n font-style: italic;\n}\n\n.loader::before {\n content: '';\n display: inline-block;\n width: 20px;\n height: 20px;\n border: 2px solid var(--color-border);\n border-top: 2px solid var(--color-primary);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-right: 0.5em;\n vertical-align: middle;\n}\n\n@keyframes spin {\n 0% { transform: rotate(0deg); }\n 100% { transform: rotate(360deg); }\n}\n\n.loading-more {\n text-align: center;\n padding: 1em 2em;\n color: var(--color-text-muted);\n font-style: italic;\n font-size: 0.9em;\n border-top: 1px solid var(--color-border);\n margin-top: 1em;\n}\n\n.loading-more::before {\n content: '';\n display: inline-block;\n width: 16px;\n height: 16px;\n border: 2px solid var(--color-border);\n border-top: 2px solid var(--color-primary);\n border-radius: 50%;\n animation: spin 1s linear infinite;\n margin-right: 0.5em;\n vertical-align: middle;\n}\n\n#history-error {\n text-align: center;\n padding: 2em;\n color: var(--color-danger-text);\n background-color: var(--color-danger);\n border: 1px solid var(--color-state-border);\n border-radius: 6px;\n margin: 1em 0;\n}\n\n#history-error p {\n margin: 0;\n}\n\n/* Breadcrumb */\n.breadcrumb {\n display: flex;\n align-items: center;\n gap: 0.5rem;\n color: var(--color-text-secondary);\n font-size: 0.875rem;\n}\n\n.breadcrumb a {\n color: var(--color-primary-light);\n text-decoration: none;\n transition: color 0.3s ease;\n}\n\n.breadcrumb a:hover {\n color: var(--color-primary);\n}\n\n/* Parameters */\n.parameter-grid {\n display: grid;\n gap: 1.5rem;\n}\n\n.parameter-item {\n background: var(--color-bg-glass);\n border: 1px solid var(--color-border);\n border-radius: 12px;\n padding: 1.5rem;\n transition: all 0.3s ease;\n}\n\n.parameter-item:hover {\n border-color: var(--color-primary);\n box-shadow: 0 0 20px rgba(99, 102, 241, 0.1);\n}\n\n.parameter-header {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n margin-bottom: 1rem;\n}\n\n.parameter-name {\n font-weight: 600;\n color: var(--color-text-primary);\n}\n\n.parameter-type {\n background: var(--color-secondary);\n color: white;\n padding: 0.25rem 0.75rem;\n border-radius: 12px; /* Reduced from 20px */\n font-size: 0.75rem;\n font-weight: 500;\n}\n\n.parameter-required {\n background: var(--color-accent);\n}\n\n.parameter-description {\n color: var(--color-text-secondary);\n margin-bottom: 1rem;\n line-height: 1.5;\n}\n\n.parameter-input {\n width: 100%;\n background: var(--color-bg-secondary);\n border: 1px solid var(--color-border);\n color: var(--color-text-primary);\n padding: 0.75rem 1rem;\n border-radius: 8px;\n font-family: inherit;\n transition: all 0.3s ease;\n}\n\n.parameter-input:focus {\n outline: none;\n border-color: var(--color-primary);\n box-shadow: 0 0 0 3px rgba(99, 102, 241, 0.1);\n}\n\n/* Preview Section */\n.preview-section {\n background: var(--color-bg-card);\n border-radius: 16px;\n border: 1px solid var(--color-border);\n overflow: hidden;\n margin-top: 2rem;\n}\n\n.preview-controls {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 1rem 2rem;\n background: var(--color-bg-glass);\n border-bottom: 1px solid var(--color-border);\n}\n\n.preview-buttons {\n display: flex;\n gap: 0.75rem;\n}\n\n.preview-iframe {\n width: 100%;\n height: 500px;\n border: none;\n background: white;\n}\n\n.back {\n width: 100%;\n margin-top: -20px;\n margin-bottom: 1.5em;\n display: block;\n color: var(--color-text-muted);\n font-size: 0.95em;\n}\n\n/* Stats Badge */\n.stats-badge {\n display: inline-flex;\n align-items: center;\n gap: 0.75rem;\n background: var(--color-bg-card);\n border: 1px solid var(--color-border);\n border-radius: 12px;\n padding: 0.75rem 1.25rem;\n margin: 1.5rem auto 0;\n box-shadow: var(--shadow-md);\n transition: all 0.3s ease;\n max-width: fit-content;\n}\n\n.stats-badge:hover {\n border-color: var(--color-border-hover);\n box-shadow: var(--shadow-lg);\n transform: translateY(-1px);\n}\n\n.stats-badge .chart-icon {\n display: flex;\n align-items: center;\n gap: 2px;\n}\n\n.stats-badge .chart-bar {\n width: 4px;\n border-radius: 2px;\n background: var(--gradient-primary);\n}\n\n.stats-badge .chart-bar:nth-child(1) {\n height: 12px;\n background: var(--color-primary-light);\n}\n\n.stats-badge .chart-bar:nth-child(2) {\n height: 16px;\n background: var(--color-primary);\n}\n\n.stats-badge .chart-bar:nth-child(3) {\n height: 20px;\n background: var(--color-primary-dark);\n}\n\n.stats-badge .badge-text {\n color: var(--color-text-primary);\n font-size: 0.875rem;\n font-weight: 500;\n white-space: nowrap;\n}\n ";
2
2
  export default _default;
@@ -207,7 +207,7 @@ body::before {
207
207
  }
208
208
 
209
209
  .theme-toggle:hover .theme-toggle-icon {
210
- transform: rotate(180deg);
210
+ transform: rotate(15deg);
211
211
  }
212
212
 
213
213
  h1, h2, h3 {
@@ -419,14 +419,14 @@ p {
419
419
  font-size: 1.15rem;
420
420
  margin: 0;
421
421
  width: 100%;
422
- color: var(--color-text-default);
422
+ color: var(--color-text-primary);
423
423
  }
424
424
 
425
425
  .componentRow .release {
426
426
  font-size: 1rem;
427
427
  margin: 0;
428
428
  width: 100%;
429
- color: var(--color-text-default);
429
+ color: var(--color-text-primary);
430
430
  }
431
431
 
432
432
  .componentRow .title .description {
@@ -552,18 +552,14 @@ select:focus {
552
552
  }
553
553
 
554
554
  .filters input {
555
- color: #0f0f23;
556
- background-color: #eee;
555
+ color: var(--color-text-primary);
556
+ background-color: var(--color-bg-card);
557
557
  }
558
558
 
559
559
  #author-filter {
560
560
  flex: 0 1 30%;
561
561
  }
562
562
 
563
- @media (min-width: 1024px) {
564
- margin-left: 15px;
565
- }
566
-
567
563
  .parameter {
568
564
  flex: 1 0;
569
565
  max-width: 25%;
@@ -578,7 +574,7 @@ select:focus {
578
574
  .author {
579
575
  flex: 0 1 15%;
580
576
  word-break: break-all;
581
- color: var(--color-info);
577
+ color: var(--color-text-secondary);
582
578
  }
583
579
 
584
580
  #href {
@@ -864,7 +860,7 @@ a.tab-link.selected {
864
860
  }
865
861
 
866
862
  .info-item {
867
- display: flow;
863
+ display: flex;
868
864
  align-items: start;
869
865
  padding: 0.75rem 0;
870
866
  border-bottom: 1px solid var(--color-border);
@@ -914,12 +910,12 @@ a.tab-link.selected {
914
910
  }
915
911
 
916
912
  ::-webkit-scrollbar-thumb {
917
- background: var(--gradient-primary);
913
+ background: var(--color-border-hover);
918
914
  border-radius: 4px;
919
915
  }
920
916
 
921
917
  ::-webkit-scrollbar-thumb:hover {
922
- background: var(--gradient-secondary);
918
+ background: var(--color-primary);
923
919
  }
924
920
 
925
921
  /* Main Content Layout */
@@ -1169,6 +1165,14 @@ a.tab-link.selected {
1169
1165
  color: var(--color-text-muted);
1170
1166
  }
1171
1167
 
1168
+ .empty-state {
1169
+ text-align: center;
1170
+ padding: 2em;
1171
+ color: var(--color-text-muted);
1172
+ font-style: italic;
1173
+ margin: 0;
1174
+ }
1175
+
1172
1176
  .loader p {
1173
1177
  margin: 0;
1174
1178
  font-style: italic;
@@ -1389,17 +1393,17 @@ a.tab-link.selected {
1389
1393
 
1390
1394
  .stats-badge .chart-bar:nth-child(1) {
1391
1395
  height: 12px;
1392
- background: #10b981; /* green */
1396
+ background: var(--color-primary-light);
1393
1397
  }
1394
1398
 
1395
1399
  .stats-badge .chart-bar:nth-child(2) {
1396
1400
  height: 16px;
1397
- background: #ef4444; /* red */
1401
+ background: var(--color-primary);
1398
1402
  }
1399
1403
 
1400
1404
  .stats-badge .chart-bar:nth-child(3) {
1401
1405
  height: 20px;
1402
- background: #3b82f6; /* blue */
1406
+ background: var(--color-primary-dark);
1403
1407
  }
1404
1408
 
1405
1409
  .stats-badge .badge-text {
@@ -7,7 +7,7 @@ exports.default = cleanRequire;
7
7
  const try_require_1 = __importDefault(require("try-require"));
8
8
  function cleanRequire(path, { justTry = false, resolve = false }) {
9
9
  const shouldThrow = !justTry;
10
- if (require.cache && !!require.cache[path]) {
10
+ if (require.cache?.[path]) {
11
11
  delete require.cache[path];
12
12
  }
13
13
  let action = shouldThrow ? require : try_require_1.default;
@@ -8,7 +8,7 @@ const node_path_1 = __importDefault(require("node:path"));
8
8
  const try_require_1 = __importDefault(require("try-require"));
9
9
  function moduleExists(moduleName) {
10
10
  const packageModulePath = node_path_1.default.join(moduleName, 'package.json');
11
- if (require.cache && !!require.cache[packageModulePath]) {
11
+ if (require.cache?.[packageModulePath]) {
12
12
  delete require.cache[packageModulePath];
13
13
  }
14
14
  return (!!try_require_1.default.resolve(moduleName) || !!try_require_1.default.resolve(packageModulePath));