Skip to content

Conversation

@iftakharul-islam
Copy link
Member

@iftakharul-islam iftakharul-islam commented Oct 29, 2025

Summary by CodeRabbit

  • New Features

    • Table of Contents block with hierarchical/numbered lists, collapsible mobile behavior, smooth scrolling, and server/client rendering
    • Contributors and Advanced Contributors blocks with configurable avatars, titles, links, date display, and responsive styling
  • Style

    • Improved responsive, RTL, print and accessibility-aware styles across blocks; refined mobile notice and link hover states
  • Chores

    • Build and asset updates to improve runtime packaging and editor integration

✏️ Tip: You can customize this high-level summary in your review settings.

@iftakharul-islam iftakharul-islam self-assigned this Oct 29, 2025
@coderabbitai
Copy link

coderabbitai bot commented Oct 29, 2025

Walkthrough

This PR adds four new Gutenberg blocks (Contributors, AdvanceContributors, TableOfContents, DocsGrid), many reusable block control components, JS/PHP helpers for generating block styles, updated build artifacts/webpack config, and multiple CSS/asset updates across editor and frontend.

Changes

Cohort / File(s) Summary
TableOfContents block
src/blocks/TableOfContents/*, assets/build/blocks/TableOfContents/*, assets/build/blocks/TableOfContents/index-rtl.css, assets/build/blocks/TableOfContents/index.css, assets/build/blocks/TableOfContents/view.js, src/blocks/TableOfContents/view.js, src/blocks/TableOfContents/render.php
New dynamic TOC block: editor UI, view.js scroll/spy/smooth-scroll, server-side render helpers (styles/content extraction), inline style generation, block.json and assets.
Contributors block
src/blocks/Contributors/*, assets/build/blocks/Contributors/*
New Contributors block: editor (edit, edit-old), save stub, server render with responsive inline CSS, attributes manifest, styles (RTL + LTR), and asset manifests.
AdvanceContributors block
src/blocks/AdvanceContributors/*, assets/build/blocks/AdvanceContributors/*
New AdvanceContributors block: richer attribute surface, edit components (new + old), server render, style sheets (RTL + LTR), and build assets.
DocsGrid block
src/blocks/DocsGrid/*, assets/build/blocks/DocsGrid/*
New DocsGrid block files and RTL/LTR styles; render.php functions wrapped with if (!function_exists(...)) guards; asset manifests and built entries.
Shared block controls & components
src/blocks/commonControls/*, src/blocks/components/*
Many reusable editor controls added: AlignmentControls, ColorsControls, DimensionsControls, BackgroundImageControls, BorderAndShadowControls, DisplayControls, TypographyControls, Spacing/Shadow/Border/Dimension/Background/TabSystem/Typography controls, etc.
Block helpers
src/blocks/helpers/*, src/blocks/helpers/block-styles.php, src/blocks/helpers/block-helpers.js, src/blocks/helpers/index.js
New PHP and JS helper libraries for generating block inline styles, typography/spacing/border/shadow builders, CSS sanitization/units, and exports. README added.
Build artifacts & webpack
assets/build/*.asset.php, assets/build/*.js, assets/build/*.css, webpack.config.js, package.json, assets/build/index.asset.php, assets/build/block.asset.php, assets/build/frontend.asset.php, assets/build/store.asset.php, assets/build/print.asset.php
Updated build outputs: added react-jsx-runtime to manifests, updated version hashes, migrated bundles to JSX runtime exports, simplified font paths, adjusted webpack asset rules (images/fonts/SVG), and swapped devDeps in package.json.
Frontend / core plugin changes
includes/Assets.php, includes/Frontend.php, wedocs.php, assets/build/frontend.css, assets/build/style-block.css, assets/build/block.css, assets/build/block-rtl.css, assets/build/index.asset.php
Added localized assetsUrl and isPro variables; commented out block style registration and template loader hook; added block category registration and dequeue logic; CSS tweaks (font path updates, minor rule removals, RTL css additions).
Misc / docs
readme.md, src/blocks/helpers/README.md
Documentation additions and README for helpers.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60–90 minutes

Possibly related issues

  • weDevsOfficial/wedocs-pro#168 — Implements the same wedocs/table-of-contents block and related render/style/view behavior; likely linked to TOC objectives.

Possibly related PRs

Suggested labels

Needs Review

Suggested reviewers

  • arifulhoque7

Poem

🐇 In a burrow of code I happily hop,
New blocks and helpers piled high in a crop.
TOC, Contributors, DocsGrid in a row,
Styles and builds all set—ready to go!
A tiny rabbit applauds this neat hop—bravo! 🥕

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 34.78% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title check ❓ Inconclusive The PR title 'Feat/pro block settings' is vague and generic, using abbreviation 'Feat' and the term 'pro block settings' without clearly specifying which blocks or features are affected. Clarify the title to describe the main changes more specifically. Examples: 'Add Table of Contents and Contributors blocks', 'Implement pro gating for Contributors block', or 'Add dynamic block rendering and styling system'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 79

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
webpack.config.js (1)

71-75: Avoid duplicate MiniCssExtractPlugin.

@wordpress/scripts already injects MiniCssExtractPlugin. A second instance can cause conflicts. Reuse the existing one unless you have a specific need.

Apply this diff:

-  plugins: [
-    ...defaultConfig.plugins,
-    new MiniCSSExtractPlugin( {
-      filename: '[name].css',
-      chunkFilename: '[id].css',
-    } ),
-  ],
+  plugins: [ ...defaultConfig.plugins ],
🧹 Nitpick comments (98)
assets/build/style-block-rtl.css (2)

1-1: Reconsider extensive use of !important flags.

The CSS contains numerous !important declarations (e.g., background-color:var(--field-color) !important), which typically indicates CSS architecture or specificity issues. Using !important broadly can make the codebase harder to maintain and override.

Review the specificity of selectors and consider restructuring to rely on proper selector hierarchy instead of !important. For example:

/* Instead of: */
.wp-block-wedocs-wedocs-search .wedocs-search-input .search-field {
  background-color: var(--field-color) !important;
}

/* Consider: */
.wp-block-wedocs-wedocs-search .wedocs-search-input .search-field {
  background-color: var(--field-color);
}

This requires ensuring the selector specificity is sufficient without needing !important.


1-1: Consider build artifact exclusion from version control.

Build artifacts are typically auto-generated and should not be committed to version control. If this file is generated during the build process, it should be excluded via .gitignore and regenerated as part of CI/CD.

Verify that assets/build/ is excluded from .gitignore and that the build pipeline regenerates these files. This keeps the repository clean and ensures artifacts stay in sync with source.

src/blocks/components/SpacingControl.js (3)

26-68: Consider extracting the duplicated BoxControl configuration.

The Padding and Margin sections share identical configuration (units, allowReset, resetValues). Extract this into a shared helper or constant to improve maintainability.

Example refactor:

+const SPACING_BOX_CONFIG = {
+	units: [
+		{ value: 'px', label: 'px' },
+		{ value: 'em', label: 'em' },
+		{ value: 'rem', label: 'rem' },
+		{ value: '%', label: '%' }
+	],
+	allowReset: true,
+	resetValues: {
+		top: '0px',
+		right: '0px',
+		bottom: '0px',
+		left: '0px'
+	}
+};
+
 const SpacingControl = ({
 	// ... props
 }) => {
 	return (
 		<PanelBody title={label} initialOpen={false}>
 			{showPadding && (
 				<>
 					<BoxControl
 						label={__('Padding', 'wedocs')}
 						values={paddingValue}
 						onChange={onPaddingChange}
-						units={[
-							{ value: 'px', label: 'px' },
-							{ value: 'em', label: 'em' },
-							{ value: 'rem', label: 'rem' },
-							{ value: '%', label: '%' }
-						]}
-						allowReset={true}
-						resetValues={{
-							top: '0px',
-							right: '0px',
-							bottom: '0px',
-							left: '0px'
-						}}
+						{...SPACING_BOX_CONFIG}
 					/>
 					<Spacer marginTop={4} marginBottom={4} />
 				</>
 			)}
 
 			{showMargin && (
 				<>
 					<BoxControl
 						label={__('Margin', 'wedocs')}
 						values={marginValue}
 						onChange={onMarginChange}
-						units={[
-							{ value: 'px', label: 'px' },
-							{ value: 'em', label: 'em' },
-							{ value: 'rem', label: 'rem' },
-							{ value: '%', label: '%' }
-						]}
-						allowReset={true}
-						resetValues={{
-							top: '0px',
-							right: '0px',
-							bottom: '0px',
-							left: '0px'
-						}}
+						{...SPACING_BOX_CONFIG}
 					/>
 					<Spacer marginTop={4} marginBottom={4} />
 				</>
 			)}
 		</PanelBody>
 	);
 };

77-77: Consider consistent default value handling.

The gapValue uses an inline fallback ('10px') while paddingValue and marginValue have default values in the props destructuring. For consistency, consider adding a default for gapValue in the props definition (line 18).


74-85: Note: API inconsistency with custom UnitControl.

This component uses WordPress's experimental UnitControl (value as a string like '10px'), while the codebase also has a custom UnitControl at src/blocks/CustomControls/UnitControl.js with a different API (separate value and unit props). Consider documenting when to use each or standardizing on one approach to avoid confusion.

src/blocks/commonControls/DisplayControls.js (1)

26-47: Consider extracting styles to a stylesheet.

While inline styles work, extracting them to a dedicated CSS file or using a CSS-in-JS solution would improve maintainability and allow for better reusability across components.

readme.md (1)

26-39: Remove misleading Mozart configuration comment from readme.md.

This commented JSON block references "WPMUDEV\PluginTest" and includes google/apiclient, but verification shows: the weDocs project has no Mozart configuration in composer.json, and google/apiclient is not used anywhere in the codebase. This appears to be accidentally copied from another project and should be deleted to avoid confusion.

src/blocks/TableOfContents/editor.scss (1)

18-24: Consider the UX implications of cursor: default on links.

The TOC list links have cursor: default but still show a hover color change. This creates an inconsistent user experience where the visual feedback (color change on hover) suggests interactivity, but the cursor doesn't change to indicate a clickable element.

If these links are not meant to be clickable in the editor (which seems to be the intent), consider either:

  1. Removing the hover color change to match the non-interactive cursor, or
  2. Using pointer-events: none to completely disable interaction and remove the need for hover styles.

Apply this diff to remove hover styles for consistency:

 	.toc-content {
 		.toc-list {
 			li a {
 				cursor: default;
-
-				&:hover {
-					color: #0073aa;
-				}
+				pointer-events: none;
 			}
 		}
 	}
assets/build/blocks/TableOfContents/style-index.css (2)

1-1: Typo in custom property name (sytle → style) and likely wrong binding.

color uses var(--list-item-sytle, inherit). Rename to a clear token (e.g., --toc-link-color) across LTR/RTL CSS and JS, and bind it to listColor (not container background).


1-1: Nit: prefer ::before/::after.

Use double-colon pseudo-elements for modern CSS.

src/blocks/commonControls/TypographyControls.js (2)

255-270: Use undefined on reset instead of null to truly clear values.

Block serialization treats undefined as “absent”; null may persist and complicate style builders. Prefer undefined.

Apply this diff:

-                                fontFamily: null,
-                                fontSize: null,
-                                fontAppearance: null,
-                                lineHeight: null,
-                                letterSpacing: null,
-                                textDecoration: null,
-                                textTransform: null,
+                                fontFamily: undefined,
+                                fontSize: undefined,
+                                fontAppearance: undefined,
+                                lineHeight: undefined,
+                                letterSpacing: undefined,
+                                textDecoration: undefined,
+                                textTransform: undefined,

49-66: Reduce repetition with a small helper.

setAttributes blocks repeat. Extract a setTypographyForDevice(key, value) helper to cut noise and mistakes.

Example:

+ const setTypographyForDevice = (key, value) => {
+   setAttributes({
+     typographyControls: {
+       ...typographyControls,
+       [device]: {
+         ...typographyControls[device],
+         [key]: value,
+       },
+     },
+   });
+ };
...
- onChange={(value) => { setAttributes({ ... }) }}
+ onChange={(value) => setTypographyForDevice('fontFamily', value)}

Also applies to: 90-107, 111-144, 149-165, 167-201, 204-242

webpack.config.js (4)

19-20: Use content hashing (or path) for emitted assets to avoid collisions and aid caching.

images/[name][ext] can overwrite when names repeat. Prefer contenthash or preserve subpaths.

Apply one:

- assetModuleFilename: 'images/[name][ext]',
+ assetModuleFilename: 'images/[name].[contenthash:8][ext]',

or:

- assetModuleFilename: 'images/[name][ext]',
+ assetModuleFilename: '[path][name][ext]',

24-31: Broaden filter to include webp/avif; otherwise rules conflict.

Default WP Scripts rules often match webp/avif; your filter leaves them, causing overlap.

Apply this diff:

- return !testString.match(/jpg|jpeg|png|gif|svg|bmp|ico/i);
+ return !testString.match(/jpg|jpeg|png|gif|svg|bmp|ico|webp|avif/i);

48-59: Brittle SVG routing by substring match.

Checking pathData.filename.includes('assets/fonts') can fail with alternate paths. Use include/exclude with resolved paths, or a dedicated fonts rule before SVG images.

Example:

- if (pathData.filename.includes('assets/fonts')) { return 'fonts/[name][ext]'; }
+ // In rules: put a fonts-first rule with `test: /\.svg$/i, include: path.resolve(__dirname, 'assets/fonts')`
+ // and a second svg rule for images with `exclude` pointing to the fonts dir.

78-94: Make devServer host configurable.

Hardcoding host 'wedocs.test' can block other devs. Read from env with a safe default.

Example:

- host: 'wedocs.test',
+ host: process.env.DEV_HOST || 'localhost',
+ port: parseInt(process.env.DEV_PORT || '8886', 10),
src/blocks/components/TypographyControl.js (3)

54-70: Use theme/gutenberg font families, not a hard‑coded list.

Pull families via useSettings('typography.fontFamilies') to respect theme.json and user fonts; fall back gracefully for classic themes.

Example snippet:

import { useSettings } from '@wordpress/block-editor';
const ff = useSettings( 'typography.fontFamilies' );
const themeFonts = ff?.[0]?.theme ?? [];
const customFonts = ff?.[0]?.custom ?? [];
const options = [{ label: __('Default','wedocs'), value: 'default' }, ...themeFonts, ...customFonts];

116-127: UnitControl defaults should be empty/undefined, not 'normal'.

UnitControl expects numeric+unit (or empty). Use placeholders and treat undefined as “inherit/normal” in style builders.

Apply this diff:

- value={value.lineHeight || 'normal'}
+ value={value.lineHeight}
...
- value={value.letterSpacing || 'normal'}
+ value={value.letterSpacing}

Then handle “normal” in CSS generation (fallback when undefined).

Also applies to: 130-140


32-33: Open by default only when needed.

Initial open Panels can be noisy. Consider initialOpen prop controlled by caller or keep it closed by default for consistency with other panels.

assets/build/blocks/TableOfContents/style-index-rtl.css (1)

1-1: Typo in custom property (sytle) and binding.

Rename var(--list-item-sytle) to --toc-link-color (or similar) and align with JS to source from listColor, not container background.

src/blocks/helpers/README.md (1)

1-120: Add minimum WP/Gutenberg versions and SSR registration snippet.

Include a short “Compatibility” section (min WP and Gutenberg) and a code snippet showing register_block_type with render_callback using these helpers for dynamic blocks. Helps adopters avoid guesswork.

assets/build/block.js (1)

1-1: Do not lint/review minified build artifacts; exclude assets/build from linters and code review.

Biome “noRedeclare / use-before-declare” errors are from minification. Add assets/build to .eslintignore/.biomeignore and CI excludes. Prefer reviewing source files with sourcemaps.

Example .biomeignore/.eslintignore entry:

assets/build/**
src/blocks/commonControls/AlignmentControls.js (2)

30-76: DRY the four nearly identical handlers

Reduce repetition and accidental divergence by using a generic updater.

Example:

-const handleDirectionAlignmentChange = (value) => { /* ...direction... */ };
-const handleTextAlignmentChange = (value) => { /* ...textAlign... */ };
-const handleHorizontalAlignmentChange = (value) => { /* ...justifyContent... */ };
-const handleVerticalAlignmentChange = (value) => { /* ...alignItems... */ };
+const updateAlignment = (key) => (value) =>
+  setAttributes({
+    alignmentControls: {
+      ...alignmentControls,
+      [device]: {
+        ...currentAlignment,
+        [key]: value,
+      },
+    },
+  });
+
+const handleDirectionAlignmentChange = updateAlignment('direction');
+const handleTextAlignmentChange = updateAlignment('textAlign');
+const handleHorizontalAlignmentChange = updateAlignment('justifyContent');
+const handleVerticalAlignmentChange = updateAlignment('alignItems');

196-219: Prefer removing keys over saving nulls on Reset

Persisting null bloats attribute storage and requires extra null checks. Remove the keys for the current device instead.

- onClick={() => {
-   setAttributes({
-     alignmentControls: {
-       ...alignmentControls,
-       [device]: {
-         ...currentAlignment,
-         textAlign: null,
-         alignItems: null,
-         justifyContent: null,
-         direction: null,
-       },
-     },
-   });
- }}
+ onClick={() => {
+   const { textAlign, alignItems, justifyContent, direction, ...rest } = currentAlignment || {};
+   setAttributes({
+     alignmentControls: {
+       ...alignmentControls,
+       [device]: rest,
+     },
+   });
+ }}

Ensure downstream CSS generation handles missing keys (undefined) correctly.

src/blocks/components/BackgroundControl.js (2)

15-27: Default onChange handlers to no-ops to prevent crashes

If a parent omits a handler, RadioControl/TextControl/MediaUpload will call undefined.

-const BackgroundControl = ({
+const BackgroundControl = ({
   label,
   backgroundType = 'classic',
-  onBackgroundTypeChange,
+  onBackgroundTypeChange = () => {},
   backgroundColor,
-  onBackgroundColorChange,
+  onBackgroundColorChange = () => {},
   backgroundGradient,
-  onBackgroundGradientChange,
+  onBackgroundGradientChange = () => {},
   backgroundImage = {},
-  onBackgroundImageChange,
+  onBackgroundImageChange = () => {},
   showGradient = true,
   showImage = true
 }) => {

31-39: Optional UX polish: clear opposite-type state on switch

Avoid stale values when toggling type.

- onChange={onBackgroundTypeChange}
+ onChange={(type) => {
+   onBackgroundTypeChange(type);
+   if (type === 'classic') onBackgroundGradientChange?.('');
+   if (type === 'gradient') onBackgroundColorChange?.('');
+ }}

Also, when selecting an image, consider fallback alt (media.alt || media.title || '').

Also applies to: 57-66, 69-107

src/blocks/commonControls/DimensionsControls.js (2)

98-154: Consistency: consider supplying explicit units to UnitControl

DimensionControl.js defines units; this component leaves defaults. Aligning units across both improves UX and predictability.

Example:

 <UnitControl
   __next40pxDefaultSize
   label={__('Fixed', 'wedocs')}
   value={currentDimensions.width || ''}
+  units={[ { value: 'px', label: 'px' }, { value: '%', label: '%' }, { value: 'em', label: 'em' }, { value: 'rem', label: 'rem' } ]}

Repeat for min/max width/height.

Also applies to: 171-227


230-258: Prefer removing keys over saving nulls on Reset

Same rationale as AlignmentControls.

- [device]: {
-   ...currentDimensions,
-   width: null,
-   minWidth: null,
-   maxWidth: null,
-   height: null,
-   minHeight: null,
-   maxHeight: null,
-   padding: null,
-   margin: null,
-   blockSpacing: null,
- },
+[device]: ((d) => {
+  const {
+    width, minWidth, maxWidth,
+    height, minHeight, maxHeight,
+    padding, margin, blockSpacing,
+    ...rest
+  } = d || {};
+  return rest;
+})(currentDimensions),
src/blocks/components/DimensionControl.js (1)

8-16: Default onChange handlers to no-ops

Prevents accidental crashes if a parent forgets a handler.

-const DimensionControl = ({
+const DimensionControl = ({
   label,
   widthValue,
-  onWidthChange,
+  onWidthChange = () => {},
   heightValue,
-  onHeightChange,
+  onHeightChange = () => {},
   showHeight = true,
   linkValues = false
 }) => {
assets/build/print-rtl.css (4)

39-40: Remove duplicate border declaration

Only the latter applies; drop the first to avoid confusion.

-  border: 1px solid #ccc;
-  border: 1px solid rgba(0, 0, 0, 0.15);
+  border: 1px solid rgba(0, 0, 0, 0.15);

36-37: Deduplicate white-space

The second overrides the first. Keep pre-wrap for readability in print.

-  white-space: pre;
-  white-space: pre-wrap;
+  white-space: pre-wrap;

55-56: Resolve conflicting font-size declarations

font-size appears twice; only last wins. Keep the intended value (15px shown later) and remove the earlier one.

-  font-size: 18px;
   line-height: 1.2em;
   border-radius: 50px;
   color: #fff;
   background: #3197d1;
   vertical-align: baseline;
   white-space: nowrap;
-  font-size: 15px;
+  font-size: 15px;

Also applies to: 62-62


141-144: Drop duplicate selector

Same selector listed twice.

-a:not(.anchorjs-link)::after,
-a:not(.anchorjs-link)::after {
+a:not(.anchorjs-link)::after {
   content: ' (' attr(href) ')';
 }
src/blocks/TableOfContents/style.scss (3)

63-67: Use logical properties to support RTL

Replace left-specific properties with logical ones.

- border-left: 3px solid #0073aa;
- padding-left: 10px;
+ border-inline-start: 3px solid #0073aa;
+ padding-inline-start: 10px;

133-135: Respect reduced motion preferences

Avoid forced smooth scrolling when users prefer reduced motion.

 html.smooth-scroll {
   scroll-behavior: smooth;
 }
+@media (prefers-reduced-motion: reduce) {
+  html.smooth-scroll {
+    scroll-behavior: auto;
+  }
+}

137-151: Avoid non-localizable CSS-generated content

The loading message is hardcoded via content: and can’t be localized/accessibility-announced. Prefer rendering this text in markup with an ARIA live region.

src/blocks/commonControls/ColorsControls.js (1)

17-17: Remove unused props

isTextColor, isBackgroundColor, isLinkColor are declared but unused. Drop them or implement conditional rendering.

assets/build/blocks/DocsGrid/index.js (2)

1-1: Avoid per_page: -1 REST queries in editor

Fetching all docs/sections/articles can be slow on large sites. Paginate or limit plus on-demand fetch to improve editor perf.


1-1: Consider excluding built assets from PRs

Minified bundles create noisy diffs and false-positive lint. Commit sources and rely on build steps or attach artifacts on releases.

assets/build/frontend-rtl.css (2)

508-516: Conflicting font-size declarations

font-size is set to 18px then 15px for the same selector; the latter wins. Remove one for clarity.

-  font-size: 18px;
   line-height: 1.2em;
   border-radius: 50px;
   color: #fff;
   background: #3197d1;
   vertical-align: baseline;
   white-space: nowrap;
-  font-size: 15px;
+  font-size: 15px;

164-168: Prefer overflow: auto for hit list

overflow: scroll always shows scrollbars; auto avoids visual noise.

-  overflow: scroll;
+  overflow: auto;
src/blocks/Contributors/edit-old.js (4)

10-23: Prune unused imports

RangeControl and ButtonGroup appear unused. Remove to reduce bundle size.


66-71: currentPost is computed but unused

Either wire it into preview/data fetching or remove it.


92-100: Avatar border radius used but not configurable here

rounded uses attributes.avatarBorderRadius, but this UI doesn’t expose a control to set it. Add a UnitControl or remove the dependency.


28-29: Remove edit-old.js — it's unused and superseded by edit.js.

Verification confirms src/blocks/Contributors/index.js imports from ./edit (not edit-old), and there are no references to edit-old.js anywhere in the codebase. The file appears to be legacy code that was fully replaced by edit.js. Keeping it risks maintenance burden and accidental edits to the wrong file.

src/blocks/helpers/block-styles.php (3)

141-149: Gradient is overridden by image; support layered backgrounds.

Currently background-image gets set twice; the URL wins and gradient is lost. Compose a single declaration:

-    if ($background_type === 'gradient' && $background_gradient) {
-        $styles[] = 'background-image: ' . esc_attr($background_gradient);
-    }
-    if (isset($background_image['url']) && !empty($background_image['url'])) {
-        $styles[] = 'background-image: url(' . esc_url($background_image['url']) . ')';
-        $styles[] = 'background-size: cover';
-        $styles[] = 'background-position: center';
-    }
+    $images = [];
+    if ($background_type === 'gradient' && $background_gradient) {
+        $images[] = esc_attr($background_gradient);
+    }
+    if (!empty($background_image['url'])) {
+        $images[] = 'url(' . esc_url($background_image['url']) . ')';
+        $styles[] = 'background-size: cover';
+        $styles[] = 'background-position: center';
+    }
+    if ($images) {
+        $styles[] = 'background-image: ' . implode(', ', $images);
+    }

Also applies to: 145-149


236-242: Avoid dropping legitimate “0” values in styles_to_css.

array_filter without a callback treats "0" as empty. Use strlen to keep "margin: 0" strings intact (future-proofing).

-    return implode('; ', array_filter($styles));
+    return implode('; ', array_filter($styles, 'strlen'));

290-311: Broaden sanitizer to modern CSS functions.

calc(), clamp(), min(), max(), and var() are common in block styles. Consider supporting them to avoid stripping valid input. Example approach (illustrative):

-    if (preg_match('/^(-?\d*\.?\d+)([a-z%]+)?$/i', $value, $matches)) {
+    if (preg_match('/^(-?\d*\.?\d+)([a-z%]+)?$/i', $value, $matches)) {
         ...
-    }
+    } elseif (preg_match('/^(calc|clamp|min|max)\(.+\)$/i', $value) || preg_match('/^var\(--[a-z0-9\-\_]+\)$/i', $value)) {
+        return $value;
+    }
src/blocks/commonControls/BackgroundImageControls.js (1)

18-19: Hoist static constants outside the component.

Move ALLOWED_MEDIA_TYPES to module scope to avoid re-allocating on every render.

-const BackgroundImageControls = ({ attributes, setAttributes, device }) => {
-    const { backgroundImageControls } = attributes;
-    const currentBackgroundImage = backgroundImageControls[device] || {};
-
-    const ALLOWED_MEDIA_TYPES = ['image'];
+const ALLOWED_MEDIA_TYPES = [ 'image' ];
+const BackgroundImageControls = ({ attributes, setAttributes, device }) => {
+    const { backgroundImageControls } = attributes;
+    const currentBackgroundImage = backgroundImageControls[device] || {};
src/blocks/AdvanceContributors/edit-old.js (3)

151-161: Use WordPress date i18n utilities for preview date.

Respect site locale/timezone for the editor preview.

-import { useSelect } from '@wordpress/data';
+import { useSelect } from '@wordpress/data';
+import { dateI18n, getSettings as getDateSettings } from '@wordpress/date';
...
-                        <span style={dateStyle}>
-                            {attributes.datePrefix} {new Date().toLocaleDateString('en-US', {
-                                year: 'numeric',
-                                month: 'long',
-                                day: 'numeric'
-                            })}
-                        </span>
+                        <span style={dateStyle}>
+                            { attributes.datePrefix } { dateI18n( getDateSettings().formats.date || 'F j, Y', Date.now() ) }
+                        </span>

292-320: Capture media ID with background image for better caching and REST usage.

Store id alongside url/alt to allow size switching and consistent serialization.

-    onSelect={(media) => setAttributes({
-        backgroundImage: { url: media.url, alt: media.alt }
-    })}
+    onSelect={(media) => setAttributes({
+        backgroundImage: { id: media.id, url: media.url, alt: media.alt }
+    })}

If server render uses IDs for responsive sources, ensure schema accepts backgroundImage.id.


33-49: Consider centralizing style generation via the new PHP helpers (parity).

Inline editor styles duplicate logic now present in src/blocks/helpers/block-styles.php. A small utility mirroring the helper on the client would reduce drift and bugs.

Happy to sketch a tiny JS style-builder to keep parity with wedocs_build_* helpers.

src/blocks/AdvanceContributors/index.js (1)

12-16: Update comment to match inline implementation.

The comment references ./save.js but the save function is defined inline. Since this block uses server-side rendering (returning null), consider either:

  1. Removing the comment, or
  2. Updating it to reflect the inline implementation
 	/**
-	 * @see ./save.js
+	 * Server-side rendered block - save returns null
 	 */
 	save: () => null,
src/blocks/TableOfContents/index.js (1)

29-35: Remove trailing whitespace.

Clean up the trailing whitespace at the end of the file.

 registerBlockType( metadata.name, {
 	/**
 	 * @see ./edit.js
 	 */
 	edit: Edit,
 } );
-	
src/blocks/Contributors/save.js (1)

1-11: Remove unused blockProps variable.

Since this is a server-rendered block that returns null, the useBlockProps.save() call and blockProps variable are unnecessary and can be removed. The import can also be removed.

-import { useBlockProps } from '@wordpress/block-editor';
-
 const Save = () => {
-	const blockProps = useBlockProps.save();
-
 	// Since this is a dynamic block that uses PHP rendering,
 	// we return null to let the server-side render function handle the output
 	return null;
 };

 export default Save;
src/blocks/TableOfContents/controls/ListItems.js (1)

18-22: Remove commented-out code.

The commented-out ColorsControls block should either be implemented or removed. Leaving commented code in production decreases maintainability.

src/blocks/Contributors/style.scss (1)

105-108: Consider removing !important if possible.

The !important flags on lines 106-107 for avatar sizing may indicate specificity issues. If possible, increase selector specificity instead to avoid !important.

.contributor-avatar {
    // Smaller avatars on mobile
    img, .default-icon {
        width: 28px;
        height: 28px;
    }
}

If these rules are being overridden elsewhere, consider refactoring the CSS architecture rather than using !important.

src/blocks/Contributors/index.js (1)

19-41: Consider extracting icon styles to constants.

The inline styles for the PRO badge could be extracted to named constants for better maintainability and reusability if this pattern is used across multiple blocks.

const PRO_BADGE_STYLES = {
    badge: {
        position: 'absolute',
        top: '22px',
        right: '-2px',
        background: '#4f47e6',
        color: 'white',
        fontSize: '9px',
        padding: '2px 3px',
        borderRadius: '3px',
        fontWeight: 'bold',
        lineHeight: 1
    },
    wrapper: {
        position: 'relative',
        display: 'inline-block'
    }
};

icon: {
    src: () => (
        <span style={PRO_BADGE_STYLES.wrapper}>
            <Icon icon={starFilled} />
            <span style={PRO_BADGE_STYLES.badge}>PRO</span>
        </span>
    ),
}
wedocs.php (1)

185-185: Remove or uncomment the AdvanceContributors block.

Line 185 has the AdvanceContributors block commented out. Either enable it or remove the comment to keep the codebase clean.

assets/build/blocks/DocsGrid/render.php (3)

10-37: Prefix or scope helper function to avoid global collisions.

get_pagination_style_tag() is unprefixed and global. Prefer wedocs_get_pagination_style_tag(), or make it a private helper inside render_wedocs_docs_grid(). The new function_exists guard helps but namespacing is safer.


183-183: Remove unused variables or implement their usage.

$total_pages and $total_articles are declared but never used. Either remove them or render pagination/article counts. This also silences PHPMD warnings.

Also applies to: 228-228


184-206: Inline <script>: consider enqueueing and optional chaining support.

Move the toggle JS to an enqueued script or wp_add_inline_script attached to the block handle to play well with CSP and caching. Also verify that optional chaining (?.) meets your supported browsers for front-end visitors.

Would you confirm your browser support baseline and whether CSP is enforced on typical installs?

src/blocks/TableOfContents/ColorsControls.js (1)

21-28: Prefer stable APIs to fetch theme palettes.

Consider using useSetting for palettes/gradients to avoid unsafe WP APIs and the eslint disable.

Example:

import { useSetting } from '@wordpress/block-editor';
const themeColors = useSetting( 'color.palette' ) || [];
const themeGradients = useSetting( 'color.gradients' ) || [];

If other controls already use useSetting (e.g., BorderAndShadowControls.js), align for consistency.

assets/build/blocks/Contributors/style-index-rtl.css (1)

1-1: Scope note: avoid cross-component bleed.

This stylesheet also targets .contributors-tab-system .components-button-group. Ensure this file is only enqueued where needed, or move editor-only styles to the editor stylesheet to avoid front-end collisions.

src/blocks/components/ShadowControl.js (3)

5-7: Avoid confusion with local UnitControl by renaming the WP import.

You already have a custom UnitControl in the codebase. Rename the WP import to clarify intent.

- __experimentalUnitControl as UnitControl,
+ __experimentalUnitControl as WPUnitControl,

And update usages:

- <UnitControl ...
+ <WPUnitControl ...

Confirm no other imports in this file shadow the same name.

Also applies to: 41-51, 55-64, 69-78, 83-92


16-21: Defensive: guard onShadowChange.

If onShadowChange is omitted, updateShadow will throw. Either require it or no-op guard:

- const updateShadow = (key, newValue) => {
-   onShadowChange({
+ const updateShadow = (key, newValue) => {
+   (onShadowChange || (() => {}))({
      ...shadowValue,
      [key]: newValue
    });
  };

96-106: API check: PanelColorSettings deprecation.

PanelColorSettings has been phased out in favor of ToolsPanel/ColorGradientControl in newer WP. If you target recent core, plan a follow-up to migrate.

assets/build/blocks/AdvanceContributors/block.json (1)

1-16: Missing textdomain in block.json

Consider adding "textdomain": "wedocs" to enable proper i18n tooling for strings in metadata.

src/blocks/components/BorderControl.js (2)

26-41: Reset width/color when switching to “None”

If users set width/color then choose “None”, stale styles may persist downstream.

Apply:

-            onChange={onBorderStyleChange}
+            onChange={(newStyle) => {
+                onBorderStyleChange(newStyle);
+                if (newStyle === 'none') {
+                    onBorderWidthChange({});
+                    onBorderColorChange(undefined);
+                }
+            }}

87-96: PanelColorSettings is deprecated in newer WP; consider ToolsPanel/ColorPalette

Future-proof by migrating to ColorSettings within ToolsPanel or use block-editor color support if applicable.

src/blocks/Contributors/render.php (1)

12-18: Unused parameters + missing $post guard

Silence analyzers and avoid fatals on non-singular contexts.

-    function render_wedocs_contributors_block($attributes, $content, $block) {
-        // Get the current post
-        $post = get_post();
+    function render_wedocs_contributors_block($attributes, $content, $block) {
+        // Silence unused params
+        unset($content, $block);
+        // Get the current post
+        $post = get_post();
+        if ( ! $post ) {
+            return '';
+        }

Also applies to: 19-39

assets/build/blocks/AdvanceContributors/style-index-rtl.css (1)

1-1: Contrast media query value and legacy prefix

  • prefers-contrast: high is non-standard; use "more" for broader support.
  • The -o-object-fit prefix is obsolete.

Apply:

-@media(prefers-contrast: high){
+@media(prefers-contrast: more){

And drop "-o-object-fit: cover".

src/blocks/AdvanceContributors/style.scss (3)

64-75: Add visible focus styles for keyboard users.

Anchors only style :hover. Include :focus-visible for parity and WCAG compliance.

 .contributor-name {
   transition: color 0.3s ease;
   text-decoration: none;
+  outline: none;
+  &:focus-visible {
+    outline: 2px solid currentColor;
+    outline-offset: 2px;
+    text-decoration: underline;
+  }
 }

49-61: Use CSS variables instead of hard-coded brand colors.

Replace fixed hex with theme variables to improve theming and dark-mode harmony.

- .default-icon {
-   background-color: #0073aa;
-   color: white;
+ .default-icon {
+   --wedocs-accent: var(--wp--preset--color--primary, #0073aa);
+   --wedocs-on-accent: var(--wp--preset--color--background, #fff);
+   background-color: var(--wedocs-accent);
+   color: var(--wedocs-on-accent);
 }
@@
-  .contributor-item {
-    .contributor-avatar .default-icon {
-      background-color: #4a90a4;
-    }
-  }
+  .contributor-item .contributor-avatar .default-icon {
+    background-color: color-mix(in oklab, var(--wedocs-accent) 70%, black);
+  }

Also applies to: 151-156


103-109: Avoid !important; raise specificity instead.

!important makes overrides harder. Prefer a more specific selector or block-scoped size token.

- img, .default-icon {
-   width: 28px !important;
-   height: 28px !important;
- }
+ img, .default-icon {
+   width: 28px;
+   height: 28px;
+ }

If collisions occur, scope via .wedocs-contributors .contributors-container .contributor-item .contributor-avatar img rather than using !important.

assets/build/blocks/TableOfContents/view.js (1)

1-1: Scope heading search to the nearest content container; reduce O(n²) and support H6.

  • Limit to the block’s nearest article/content container to avoid cross-picking headings from the whole page.
  • Replace Array.from(list).indexOf(node) with the loop index.
  • Initialize counters up to H6.
- const c=document.querySelector(".entry-content, .post-content, main, .content")||document.body
+ const c = t.closest("article, .entry-content, .post-content, main, .content") || document.body;
@@
- const i={1:0,2:0,3:0,4:0,5:0};
+ const i={1:0,2:0,3:0,4:0,5:0,6:0};
@@
- t.forEach(function(e){
-   const l=parseInt(e.tagName.charAt(1))
+ t.forEach(function(e, idx){
+   const l = Math.min(6, parseInt(e.tagName.charAt(1), 10) || 2);
@@
-   const a = e.id || "toc-heading-"+Array.from(t).indexOf(e);
+   const a = e.id || "toc-heading-" + idx;
src/blocks/DocsGrid/render.php (4)

183-183: Remove or use $total_pages; currently unused.

Either render pagination or drop the variable. See next comment for adding pagination.

- $total_pages = $docs_query->max_num_pages;
+ $total_pages = $docs_query->max_num_pages; // Use below if pagination is enabled.

42-53: Wire up pagination rendering and style variables.

Attributes include pagination settings but output is missing; also get_pagination_style_tag() is never used.

@@
-        $show_view_details = $attributes['showViewDetails'] ?? true;
+        $show_view_details = $attributes['showViewDetails'] ?? true;
+        $enable_pagination = $attributes['enablePagination'] ?? false;
@@
-        // Query docs with pagination
+        // Query docs with pagination
         $docs_query = new WP_Query($args);
@@
-        echo $toggle_script;
-        // Output hover styles
-        echo $hover_styles;
+        // Pagination CSS variables
+        echo get_pagination_style_tag( $attributes );
+        echo $toggle_script;
+        echo $hover_styles;
@@
-            </div>
-        </div>
+            </div>
+        </div>
+        <?php if ( $enable_pagination && $docs_per_page !== 'all' && $total_pages > 1 ) : ?>
+            <nav class="wedocs-docs-grid__pagination" aria-label="<?php esc_attr_e('Docs navigation', 'wedocs'); ?>">
+                <?php
+                echo paginate_links( array(
+                    'total'   => $total_pages,
+                    'current' => max( 1, (int) $current_page ),
+                    'type'    => 'list',
+                    'prev_text' => __('Previous', 'wedocs'),
+                    'next_text' => __('Next', 'wedocs'),
+                ) );
+                ?>
+            </nav>
+        <?php endif; ?>
         <?php
         return ob_get_clean();

Also applies to: 158-171, 210-213, 319-323


256-257: Compose inline styles once and escape as a whole.

Avoid mixing escaped and raw CSS fragments inside the attribute.

- <h4 class="wedocs-docs-grid__section-title"
-     style="<?php echo esc_attr($title_style); ?> display: flex; justify-content: space-between; align-items: center;">
+ <?php $section_title_style = trim($title_style . ' display:flex; justify-content:space-between; align-items:center;'); ?>
+ <h4 class="wedocs-docs-grid__section-title" style="<?php echo esc_attr( $section_title_style ); ?>">

228-228: Remove $total_articles or implement usage.

Declared but never used.

- $total_articles = 0;
+ // $total_articles reserved for future use; remove if not needed.
src/blocks/commonControls/BorderAndShadowControls.js (3)

123-131: Avoid boolean className.

Passing false can stringify to "false". Use a conditional string.

- className={isOpen && 'is-open'}
+ className={isOpen ? 'is-open' : undefined}

215-237: Reset to undefined/null to fall back cleanly.

Setting empty objects keeps truthy values around. Prefer null/undefined to fully reset.

- border: {},
- borderRadius: null,
- boxShadow: {},
+ border: undefined,
+ borderRadius: undefined,
+ boxShadow: undefined,

35-46: Confirm boxShadow key naming consistency.

This control uses { x, y, blur, spread, color, inset }. Ensure all consumers/readers (renderers/styles) expect these keys (not horizontal/vertical). If not, map keys at the boundary.

src/blocks/Contributors/block.json (1)

27-30: Potential contrast issue for titleColor default.

Title defaults to #fff while backgroundColor defaults to #f9f9f9; visually OK, but if a theme sets a white background it may become invisible. Consider a darker default (e.g., #111).

src/blocks/TableOfContents/Inspector.js (1)

19-77: Unify textdomain with the block’s domain (“wedocs”).

Strings use 'dynamic-table-of-contents-block-wp' while block.json declares 'wedocs'. Aligning domains improves translation loading.

- __('TOC Title', 'dynamic-table-of-contents-block-wp')
+ __('TOC Title', 'wedocs')
# Apply to all __() calls in this file.

Also applies to: 94-223

assets/build/blocks/Contributors/render.php (2)

290-306: Small UX/accessibility hardening on avatar rendering.

  • Add loading="lazy" and decoding="async" to .
  • Mark the default icon container as aria-hidden.
-                    $output .= '<img src="' . esc_url($avatar_url) . '" alt="' . esc_attr($contributor->display_name) . '" style="' . wedocs_styles_to_css($avatar_styles) . '">';
+                    $output .= '<img src="' . esc_url($avatar_url) . '" alt="' . esc_attr($contributor->display_name) . '" loading="lazy" decoding="async" style="' . wedocs_styles_to_css($avatar_styles) . '">';
...
-                    $output .= '<div class="default-icon" style="' . wedocs_styles_to_css($icon_styles) . '">';
+                    $output .= '<div class="default-icon" aria-hidden="true" style="' . wedocs_styles_to_css($icon_styles) . '">';

12-12: Silence PHPMD UnusedFormalParameter for $content and $block.

WP render callbacks accept ($attributes, $content, $block) even if unused. Prefix unused params to signal intent.

-    function render_wedocs_contributors_block($attributes, $content, $block) {
+    function render_wedocs_contributors_block($attributes, $_content = null, $_block = null) {

Alternatively, add a PHPMD ignore for these params.

src/blocks/TableOfContents/edit.js (1)

154-163: Typo in CSS custom property name.

"--list-item-sytle" → "--list-item-style" (or remove if unused). Typo prevents styles from applying.

-            "--list-item-sytle": containerBackgroundColor,
+            "--list-item-style": containerBackgroundColor,
src/blocks/TableOfContents/view.js (3)

57-61: Avoid assembling HTML with strings; build DOM nodes to reduce XSS/escaping risk.

Even with textContent, innerHTML concatenation is fragile. Prefer createElement/append with textContent.

Example replacement for this block:

-        const tocHTML = generateTOCHTML(headings, supportedHeadings, showHierarchy, showNumbering);
-        const tocContent = tocBlock.querySelector('.toc-content');
-        tocContent.innerHTML = tocHTML;
+        const tocContent = tocBlock.querySelector('.toc-content');
+        tocContent.innerHTML = '';
+        tocContent.appendChild(
+          generateTOCListElement(headings, supportedHeadings, showHierarchy, showNumbering)
+        );

…with a new generateTOCListElement that returns a UL element constructed via createElement.


150-160: Add a11y state to collapsible behavior.

Toggle aria-expanded on the title and aria-hidden on the content; announce via role="button".

-        if (title && content) {
-            title.addEventListener('click', function() {
-                title.classList.toggle('collapsed');
-                content.classList.toggle('collapsed');
-            });
-        }
+        if (title && content) {
+            title.setAttribute('role', 'button');
+            title.setAttribute('aria-controls', 'toc-content');
+            title.setAttribute('aria-expanded', 'true');
+            content.id = 'toc-content';
+            title.addEventListener('click', function() {
+                const expanded = title.getAttribute('aria-expanded') === 'true';
+                title.setAttribute('aria-expanded', String(!expanded));
+                title.classList.toggle('collapsed');
+                content.classList.toggle('collapsed');
+                content.setAttribute('aria-hidden', String(expanded));
+            });
+        }

217-236: Preserve URL hash on smooth scroll.

Currently prevents default without updating history, so deep links don’t work. Push the hash after scrolling.

                 if (targetElement) {
                     const offsetTop = targetElement.offsetTop - 80; // Account for sticky headers
@@
                     } else {
                         // Fallback smooth scroll
                         animateScrollTo(offsetTop, 600);
                     }
+                    // Update hash without jump
+                    history.replaceState(null, '', '#' + targetId);
                 }
src/blocks/AdvanceContributors/edit.js (2)

164-179: Parallelize manual user fetch to reduce editor latency.

Serial await in a loop is slow with many users. Use Promise.all and filter nulls.

-                        if (attributes.selectedContributors.length > 0) {
-                            for (const userId of attributes.selectedContributors) {
-                                try {
-                                    const user = await wp.apiFetch({
-                                        path: `/wp/v2/users/${userId}?context=edit`
-                                    });
-                                    if (user) {
-                                        contributors.push(user);
-                                    }
-                                } catch (error) {
-                                    console.warn(`Could not fetch user ${userId}:`, error);
-                                }
-                            }
-                        }
+                        if (attributes.selectedContributors.length > 0) {
+                            const fetched = await Promise.all(
+                                attributes.selectedContributors.map((userId) =>
+                                    wp.apiFetch({ path: `/wp/v2/users/${userId}?context=edit` }).catch((e) => {
+                                        console.warn(`Could not fetch user ${userId}:`, e);
+                                        return null;
+                                    })
+                                )
+                            );
+                            contributors.push(...fetched.filter(Boolean));
+                        }

193-221: Minor: also dedupe against the main author when merging revisions.

You already track contributorIds; ensure main author is included initially to avoid duplicates.

-                                const contributorIds = [currentPost.author];
+                                const contributorIds = [currentPost.author];

This is correct as written. Please verify that get users for both main author and revisions do not produce duplicates in displayContributors. If duplicates appear, add a final Map by id when setting state:

-                setActualContributors(contributors);
+                const uniq = Array.from(new Map(contributors.map(u => [u.id || u.ID, u])).values());
+                setActualContributors(uniq);
src/blocks/TableOfContents/render.php (1)

14-44: Emit styles via wp_add_inline_style and traverse nested blocks.

  • Printing a raw <style> in wp_head is brittle. Prefer wp_add_inline_style against an enqueued handle.
  • parse_blocks() only inspects top-level blocks; recurse innerBlocks to style nested TOCs.
- add_action( 'wp_head', 'wedocs_dynamic_table_of_contents_inline_styles' );
+ add_action( 'wp_enqueue_scripts', 'wedocs_dynamic_table_of_contents_inline_styles', 20 );
@@
-        $blocks = parse_blocks( $post->post_content );
-        $styles = '';
-        foreach ( $blocks as $block ) {
+        $blocks  = parse_blocks( $post->post_content );
+        $styles  = '';
+        $walker  = function( $blocks ) use ( &$styles ) {
+            foreach ( $blocks as $block ) {
+                if ( 'wedocs/table-of-contents' === ( $block['blockName'] ?? '' ) ) {
+                    $attributes = $block['attrs'] ?? array();
+                    $block_id   = $attributes['blockId'] ?? '';
+                    if ( $block_id ) {
+                        $styles .= wedocs_generate_toc_styles( $attributes, $block_id );
+                    }
+                }
+                if ( ! empty( $block['innerBlocks'] ) ) {
+                    $walker( $block['innerBlocks'] );
+                }
+            }
+        };
+        $walker( $blocks );
@@
-        if ( ! empty( $styles ) ) {
-            echo '<style id="dynamic-toc-styles">' . $styles . '</style>';
-        }
+        if ( ! empty( $styles ) ) {
+            // Ensure 'wedocs-toc' (or actual handle) is registered/enqueued beforehand.
+            wp_add_inline_style( 'wedocs-toc', $styles );
+        }

Also applies to: 25-37, 39-44

src/blocks/helpers/block-helpers.js (4)

23-31: Gradient overwritten by image; honor backgroundType.

When backgroundType is 'gradient', subsequent backgroundImage url() assignment overrides it. Gate the image path by type.

- if (attributes.backgroundImage?.url) {
+ if (attributes.backgroundType !== 'gradient' && attributes.backgroundImage?.url) {
     styles.backgroundImage = `url(${attributes.backgroundImage.url})`;
     styles.backgroundSize = 'cover';
     styles.backgroundPosition = 'center';
 }

250-267: Allow common CSS functions (calc, var, clamp).

Current validator rejects calc()/var()/clamp(). Broaden acceptance to typical safe patterns.

- const regex = /^(-?\d*\.?\d+)([a-z%]+)?$/i;
+ const functionOk = /^(calc|var|clamp)\(/i.test(value.trim());
+ if (functionOk) return true;
+ const regex = /^(-?\d*\.?\d+)([a-z%]+)?$/i;

374-390: Guard for SSR/Node usage.

Accessing window breaks SSR/tests. Add typeof window check and default false.

-export const isBreakpoint = (breakpoint) => {
-  const breakpoints = getBreakpoints();
-  const width = window.innerWidth;
+export const isBreakpoint = (breakpoint) => {
+  if (typeof window === 'undefined') return false;
+  const breakpoints = getBreakpoints();
+  const width = window.innerWidth;

231-241: Expose cancel() on debounce for cleanup in effects.

Helps avoid stray timers.

 export const debounce = (func, wait) => {
   let timeout;
-  return function executedFunction(...args) {
+  const debounced = function executedFunction(...args) {
     const later = () => {
       clearTimeout(timeout);
       func(...args);
     };
     clearTimeout(timeout);
     timeout = setTimeout(later, wait);
   };
+  debounced.cancel = () => clearTimeout(timeout);
+  return debounced;
 };

@@ -1 +1 @@
(()=>{"use strict";var e,t={418:(e,t,o)=>{var l=o(609),a=Symbol.for("react.element"),r=(Symbol.for("react.fragment"),Object.prototype.hasOwnProperty),n=l.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.ReactCurrentOwner,i={key:!0,ref:!0,__self:!0,__source:!0};t.jsx=function(e,t,o){var l,d={},s=null,c=null;for(l in void 0!==o&&(s=""+o),void 0!==t.key&&(s=""+t.key),void 0!==t.ref&&(c=t.ref),t)r.call(t,l)&&!i.hasOwnProperty(l)&&(d[l]=t[l]);if(e&&e.defaultProps)for(l in t=e.defaultProps)void 0===d[l]&&(d[l]=t[l]);return{$$typeof:a,type:e,key:s,ref:c,props:d,_owner:n.current}}},706:(e,t,o)=>{e.exports=o(418)},445:(e,t,o)=>{var l=o(609);const a=window.wp.blocks,r=window.wp.i18n,n=window.wp.primitives;var i=o(706);const d=(0,i.jsx)(n.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,i.jsx)(n.Path,{d:"M12 8c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm0 6.5c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zM12.8 3h-1.5v3h1.5V3zm-1.6 18h1.5v-3h-1.5v3zm6.8-9.8v1.5h3v-1.5h-3zm-12 0H3v1.5h3v-1.5zm9.7 5.6 2.1 2.1 1.1-1.1-2.1-2.1-1.1 1.1zM8.3 7.2 6.2 5.1 5.1 6.2l2.1 2.1 1.1-1.1zM5.1 17.8l1.1 1.1 2.1-2.1-1.1-1.1-2.1 2.1zM18.9 6.2l-1.1-1.1-2.1 2.1 1.1 1.1 2.1-2.1z"})}),s=(0,i.jsx)(n.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,i.jsx)(n.Path,{fillRule:"evenodd",d:"M10.289 4.836A1 1 0 0111.275 4h1.306a1 1 0 01.987.836l.244 1.466c.787.26 1.503.679 2.108 1.218l1.393-.522a1 1 0 011.216.437l.653 1.13a1 1 0 01-.23 1.273l-1.148.944a6.025 6.025 0 010 2.435l1.149.946a1 1 0 01.23 1.272l-.653 1.13a1 1 0 01-1.216.437l-1.394-.522c-.605.54-1.32.958-2.108 1.218l-.244 1.466a1 1 0 01-.987.836h-1.306a1 1 0 01-.986-.836l-.244-1.466a5.995 5.995 0 01-2.108-1.218l-1.394.522a1 1 0 01-1.217-.436l-.653-1.131a1 1 0 01.23-1.272l1.149-.946a6.026 6.026 0 010-2.435l-1.148-.944a1 1 0 01-.23-1.272l.653-1.131a1 1 0 011.217-.437l1.393.522a5.994 5.994 0 012.108-1.218l.244-1.466zM14.929 12a3 3 0 11-6 0 3 3 0 016 0z",clipRule:"evenodd"})}),c=window.wp.element,u=window.wp.blockEditor,p=window.wp.components,g=({label:e,value:t,unit:o,onValueChange:a,onUnitChange:n})=>(0,l.createElement)(p.Flex,null,(0,l.createElement)(p.FlexBlock,null,(0,l.createElement)(p.TextControl,{label:e,value:parseInt(t),onChange:e=>a(e)})),(0,l.createElement)(p.FlexItem,null,(0,l.createElement)(p.SelectControl,{label:(0,r.__)("Unit","wedocs"),value:o,options:[{label:"px",value:"px"},{label:"%",value:"%"}],onChange:e=>n(e)}))),m=({selected:e,options:t,onChange:o})=>(0,l.createElement)(p.BaseControl,null,(0,l.createElement)("div",{className:"radio-image-control-options"},t.map((t=>(0,l.createElement)("div",{key:t.value,className:"radio-image-option"},(0,l.createElement)("input",{type:"radio",id:`radio-image-${t.value}`,value:t.value,checked:e===t.value,onChange:e=>o(e.target.value)}),(0,l.createElement)("label",{htmlFor:`radio-image-${t.value}`},t.icon&&(0,l.createElement)("i",{className:`dashicons ${t.icon}`}),t.img&&(0,l.createElement)("img",{src:t.img,alt:t.label}),t?.svg)))))),b={hideSearch:{type:"boolean",default:!1},searchWidth:{type:"number",default:50},widthUnit:{type:"string",default:"%"},placeholder:{type:"string",default:(0,r.__)("Search for a top or question","wedocs")},alignment:{type:"string",default:"right"},bgColor:{type:"string",default:"#FFFFFF"},hoverColor:{type:"string",default:"#FFFFFF"},padding:{type:"object",default:{top:14,left:22,right:22,bottom:14}},margin:{type:"object",default:{top:0,left:0,right:0,bottom:0}},borderColor:{type:"string",default:"#cccccc"},borderType:{type:"string",default:"solid"},borderWidth:{type:"number",default:1},borderRadius:{type:"number",default:30},iconColor:{type:"string",default:"#FFFFFF"},iconBgColor:{type:"string",default:"#3b82f6"},iconHoverColor:{type:"string",default:"#2563eb"},svgHoverColor:{type:"string",default:"#FFFFFF"},btnPadding:{type:"object",default:{top:24,left:26,right:26,bottom:24}},btnPosition:{type:"object",default:{top:0,right:0,bottom:10}},btnRadius:{type:"number",default:30}};(0,a.registerBlockType)("wedocs/wedocs-search",{attributes:b,save:({attributes:e})=>{const{margin:t,bgColor:o,padding:a,btnRadius:r,alignment:n,iconColor:i,widthUnit:d,hoverColor:s,borderType:p,hideSearch:g,btnPadding:m,searchWidth:b,btnPosition:h,placeholder:_,borderColor:v,borderWidth:C,iconBgColor:w,borderRadius:f,svgHoverColor:E,iconHoverColor:x}=e;if(g)return;const y={display:"flex",justifyContent:n},B={border:`${C}px ${p} ${v}`,paddingTop:a?.top,paddingLeft:a?.left,paddingRight:a?.right,borderRadius:`${f}px`,paddingBottom:a?.bottom,"--field-color":o,"--field-bg-color":s},S={top:h?.top,left:h?.left,right:h?.right,bottom:h?.bottom,height:"auto",paddingTop:m?.top,paddingLeft:m?.left,borderRadius:r,paddingRight:m?.right,paddingBottom:m?.bottom,"--field-icon-color":i,"--field-btn-bg-color":w,"--field-icon-hover-color":E,"--field-btn-bg-hover-color":x};return(0,l.createElement)(c.Fragment,null,(0,l.createElement)("form",{method:"get",role:"search",action:weDocsBlockVars?.siteUrl,...u.useBlockProps.save({className:"search-form wedocs-search-form"})},(0,l.createElement)("div",{style:y},(0,l.createElement)("div",{className:"wedocs-search-input",style:{width:b+d,marginTop:t?.top,marginLeft:t?.left,marginRight:t?.right,marginBottom:t?.bottom}},(0,l.createElement)("input",{name:"s",type:"search",style:B,className:"search-field",placeholder:_}),(0,l.createElement)("input",{type:"hidden",name:"post_type",value:"docs"}),(0,l.createElement)("button",{type:"submit",style:S,className:"search-submit"},(0,l.createElement)("svg",{width:"15",height:"16",fill:"none"},(0,l.createElement)("path",{fillRule:"evenodd",d:"M11.856 10.847l2.883 2.883a.89.89 0 0 1 0 1.257c-.173.174-.401.261-.629.261s-.455-.087-.629-.261l-2.883-2.883c-1.144.874-2.532 1.353-3.996 1.353a6.56 6.56 0 0 1-4.671-1.935c-2.576-2.575-2.576-6.765 0-9.341C3.179.934 4.839.247 6.603.247s3.424.687 4.671 1.935a6.56 6.56 0 0 1 1.935 4.67 6.55 6.55 0 0 1-1.353 3.995zM3.189 3.439c-1.882 1.882-1.882 4.945 0 6.827.912.912 2.124 1.414 3.414 1.414s2.502-.502 3.414-1.414 1.414-2.124 1.414-3.413-.502-2.502-1.414-3.413-2.124-1.414-3.414-1.414-2.502.502-3.414 1.414z"})))))))},edit:({attributes:e,setAttributes:t})=>{const o=(0,u.useBlockProps)(),{margin:a,bgColor:n,padding:i,btnRadius:b,alignment:h,iconColor:_,widthUnit:v,hoverColor:C,borderType:w,hideSearch:f,btnPadding:E,searchWidth:x,btnPosition:y,placeholder:B,borderColor:S,borderWidth:k,iconBgColor:F,borderRadius:P,svgHoverColor:R,iconHoverColor:T}=e;console.log("editor panel:",n);const M=[{value:"left",label:(0,r.__)("Align left","wedocs"),svg:(0,l.createElement)("svg",{width:"24",height:"25",fill:"none",strokeWidth:"2",strokeLinecap:"round",stroke:"left"===h?"#007cba":"#939494",strokeLinejoin:"round"},(0,l.createElement)("path",{d:"M8 9.462h12m-12 6h6m-10-9v12"}))},{value:"center",label:(0,r.__)("Align center","wedocs"),svg:(0,l.createElement)("svg",{width:"24",height:"25",fill:"none",strokeWidth:"2",strokeLinecap:"round",stroke:"center"===h?"#007cba":"#939494",strokeLinejoin:"round"},(0,l.createElement)("path",{d:"M18 9.462H6m8.99 6h-6"}),(0,l.createElement)("path",{d:"M12 6.462v12"}))},{value:"right",label:(0,r.__)("Align right","wedocs"),svg:(0,l.createElement)("svg",{width:"24",height:"25",fill:"none",strokeWidth:"2",strokeLinecap:"round",stroke:"right"===h?"#007cba":"#939494",strokeLinejoin:"round"},(0,l.createElement)("path",{d:"M16 9.462H4m12 6h-6m10-9v12"}))}],[N,D]=(0,c.useState)(!1),[O,$]=(0,c.useState)(!1),[L,A]=(0,c.useState)(!1),H={display:"flex",justifyContent:h},j={border:`${k}px ${w} ${S}`,paddingTop:i?.top,background:N?C:n,paddingLeft:i?.left,paddingRight:i?.right,borderRadius:`${P}px`,paddingBottom:i?.bottom},I={top:y?.top,left:y?.left,right:y?.right,bottom:y?.bottom,height:"auto",background:L?T:F,paddingTop:E?.top,paddingLeft:E?.left,borderRadius:b,paddingRight:E?.right,paddingBottom:E?.bottom},V=[{label:(0,r.__)("Solid","wedocs"),value:"solid"},{label:(0,r.__)("Dotted","wedocs"),value:"dotted"},{label:(0,r.__)("Dashed","wedocs"),value:"dashed"},{label:(0,r.__)("Double","wedocs"),value:"double"},{label:(0,r.__)("Groove","wedocs"),value:"groove"},{label:(0,r.__)("Ridge","wedocs"),value:"ridge"},{label:(0,r.__)("Inset","wedocs"),value:"inset"},{label:(0,r.__)("Outset","wedocs"),value:"outset"},{label:(0,r.__)("None","wedocs"),value:"none"},{label:(0,r.__)("Hidden","wedocs"),value:"hidden"}];return(0,l.createElement)(c.Fragment,null,(0,l.createElement)(u.InspectorControls,null,(0,l.createElement)(p.PanelBody,null,(0,l.createElement)(p.ToggleControl,{checked:f,className:"wedocs-search-toggle",label:(0,r.__)("Disable Block","wedocs"),onChange:e=>t({hideSearch:e})})),!f&&(0,l.createElement)(c.Fragment,null,(0,l.createElement)(p.PanelBody,{title:(0,r.__)("Color Settings","wedocs"),icon:d,initialOpen:!1,className:"wedocs-search-color-settings"},(0,l.createElement)(u.PanelColorSettings,{colors:[{name:"Sweet",color:"#F43F5E"},{name:"Orange",color:"#F97316"},{name:"Yellow",color:"#FACC15"},{name:"Purple",color:"#8B5CF6"},{name:"Light Blue",color:"#3B82F6"},{name:"Light Green",color:"#10B981"}],colorSettings:[{value:n,label:(0,r.__)("Field Background Color","wedocs"),onChange:e=>t({bgColor:e})},{value:C,label:(0,r.__)("Field Hover Color","wedocs"),onChange:e=>t({hoverColor:e})},{value:S,label:(0,r.__)("Border Color","wedocs"),onChange:e=>t({borderColor:e})},{value:_,label:(0,r.__)("Icon Color","wedocs"),onChange:e=>t({iconColor:e})},{value:F,label:(0,r.__)("Button Color","wedocs"),onChange:e=>t({iconBgColor:e})},{value:T,label:(0,r.__)("Button Hover Color","wedocs"),onChange:e=>t({iconHoverColor:e})},{value:R,label:(0,r.__)("Icon Hover Color","wedocs"),onChange:e=>t({svgHoverColor:e})}]})),(0,l.createElement)(p.PanelBody,{title:(0,r.__)("Search Bar Settings","wedocs"),icon:s},(0,l.createElement)(g,{unit:v,value:x,label:(0,r.__)("Field Width","wedocs"),onUnitChange:e=>t({widthUnit:e}),onValueChange:e=>t({searchWidth:e?parseInt(e):0})}),(0,l.createElement)(p.TextControl,{value:B,label:(0,r.__)("Placeholder","wedocs"),placeholder:(0,r.__)("Search bar placeholder","wedocs"),onChange:e=>t({placeholder:e})}),(0,l.createElement)("p",{style:{fontSize:11}},(0,r.__)("POSITION","wedocs")),(0,l.createElement)(m,{selected:h,options:M,onChange:e=>t({alignment:e})}),(0,l.createElement)(p.__experimentalBoxControl,{resetValues:{top:"14px",left:"22px",right:"22px",bottom:"14px"},values:i,label:(0,r.__)("Field Padding","wedocs"),onChange:e=>t({padding:e})}),(0,l.createElement)(p.__experimentalBoxControl,{resetValues:{top:"0px",left:"0px",right:"0px",bottom:"0px"},values:a,label:(0,r.__)("Field Margin","wedocs"),onChange:e=>t({margin:e})}),(0,l.createElement)(p.RangeControl,{min:0,max:10,value:k,label:(0,r.__)("Border Width","wedocs"),onChange:e=>t({borderWidth:e})}),(0,l.createElement)(p.RangeControl,{min:0,max:100,value:P,label:(0,r.__)("Border Radius","wedocs"),onChange:e=>t({borderRadius:e})}),(0,l.createElement)(p.SelectControl,{value:w,options:V,label:(0,r.__)("Border Type","wedocs"),onChange:e=>t({borderType:e})}),(0,l.createElement)(p.__experimentalBoxControl,{resetValues:{top:"24px",left:"26px",right:"26px",bottom:"24px"},values:E,label:(0,r.__)("Button Padding","wedocs"),onChange:e=>t({btnPadding:e})}),(0,l.createElement)(p.__experimentalBoxControl,{resetValues:{top:"0px",right:"0px",bottom:"10px"},values:y,label:(0,r.__)("Button Margin","wedocs"),onChange:e=>t({btnPosition:e})}),(0,l.createElement)(p.RangeControl,{min:0,max:100,value:b,label:(0,r.__)("Button Radius","wedocs"),onChange:e=>t({btnRadius:e})})))),(0,l.createElement)("div",{...o,style:H},(0,l.createElement)("div",{className:"wedocs-editor-search-input",style:{width:x+v,marginTop:a?.top,marginLeft:a?.left,marginRight:a?.right,marginBottom:a?.bottom}},(0,l.createElement)("input",{readOnly:!0,style:j,className:"search-field",placeholder:B,onMouseEnter:()=>D(!0),onMouseLeave:()=>D(!1)}),(0,l.createElement)("input",{type:"hidden",name:"post_type",value:"docs"}),(0,l.createElement)("button",{type:"submit",style:I,className:"search-submit",onMouseEnter:()=>A(!0),onMouseLeave:()=>A(!1)},(0,l.createElement)("svg",{width:"15",height:"16",fill:"none",onMouseEnter:()=>$(!0),onMouseLeave:()=>$(!1)},(0,l.createElement)("path",{fill:O?R:_,fillRule:"evenodd",d:"M11.856 10.847l2.883 2.883a.89.89 0 0 1 0 1.257c-.173.174-.401.261-.629.261s-.455-.087-.629-.261l-2.883-2.883c-1.144.874-2.532 1.353-3.996 1.353a6.56 6.56 0 0 1-4.671-1.935c-2.576-2.575-2.576-6.765 0-9.341C3.179.934 4.839.247 6.603.247s3.424.687 4.671 1.935a6.56 6.56 0 0 1 1.935 4.67 6.55 6.55 0 0 1-1.353 3.995zM3.189 3.439c-1.882 1.882-1.882 4.945 0 6.827.912.912 2.124 1.414 3.414 1.414s2.502-.502 3.414-1.414 1.414-2.124 1.414-3.413-.502-2.502-1.414-3.413-2.124-1.414-3.414-1.414-2.502.502-3.414 1.414z"})))),f&&(0,l.createElement)("div",{className:"backdrop"})))},icon:(0,l.createElement)("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none"},(0,l.createElement)("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M8.91421 1.5H5.5C4.39543 1.5 3.5 2.39543 3.5 3.5V6.91421V9.02779V15.5C3.5 16.6046 4.39543 17.5 5.5 17.5H7.02779C6.07771 16.4385 5.5 15.0367 5.5 13.5C5.5 10.1863 8.18629 7.5 11.5 7.5C13.0367 7.5 14.4385 8.07771 15.5 9.02779V8.5V6.91421C15.5 6.38378 15.2893 5.87507 14.9142 5.5L11.5 2.08579C11.1249 1.71071 10.6162 1.5 10.0858 1.5H8.91421ZM15.5 13.5C15.5 11.2909 13.7091 9.5 11.5 9.5C9.29086 9.5 7.5 11.2909 7.5 13.5C7.5 15.7091 9.29086 17.5 11.5 17.5C12.2414 17.5 12.9364 17.2977 13.5318 16.946L14.7929 18.2071C15.1834 18.5976 15.8166 18.5976 16.2071 18.2071C16.5976 17.8166 16.5976 17.1834 16.2071 16.7929L14.946 15.5318C15.2977 14.9364 15.5 14.2414 15.5 13.5ZM11.5 11.5C12.6046 11.5 13.5 12.3954 13.5 13.5C13.5 14.0526 13.2772 14.5512 12.9142 14.9142C12.5512 15.2772 12.0526 15.5 11.5 15.5C10.3954 15.5 9.5 14.6046 9.5 13.5C9.5 12.3954 10.3954 11.5 11.5 11.5Z",fill:"#111827"})),title:(0,r.__)("weDocs - Searchbar","wedocs"),keywords:["Search","weDocs search bar","Bar"],category:"widgets",description:(0,r.__)("Simple search forms for easy user guidance for your documentation","wedocs")});const h=({attributes:e,setAttributes:t})=>{const o=e=>o=>{t({[e]:o})},a=((0,r.__)("Solid","wedocs"),(0,r.__)("Dashed","wedocs"),(0,r.__)("Dotted","wedocs"),(0,r.__)("None","wedocs"),[{name:"Sweet",color:"#F43F5E"},{name:"Orange",color:"#F97316"},{name:"Yellow",color:"#FACC15"},{name:"Purple",color:"#8B5CF6"},{name:"Light Blue",color:"#3B82F6"},{name:"Light Green",color:"#10B981"}]);return(0,l.createElement)(l.Fragment,null,(0,l.createElement)(p.PanelBody,{title:(0,r.__)("Grid Styles","wedocs"),icon:"admin-appearance",initialOpen:!1},(0,l.createElement)("label",null,(0,r.__)("Colors","wedocs")),(0,l.createElement)(u.PanelColorSettings,{colors:a,colorSettings:[{value:e.docTitleColor,label:(0,r.__)("Doc Title Color","wedocs"),onChange:e=>o("docTitleColor")(e)},{value:e.docChildrenActiveColor,label:(0,r.__)("Doc Children Active Color","wedocs"),onChange:e=>o("docChildrenActiveColor")(e)},{value:e.borderColor,label:(0,r.__)("Border Color","wedocs"),onChange:e=>o("borderColor")(e)}]}),(0,l.createElement)(p.__experimentalBoxControl,{label:(0,r.__)("Grid Padding","wedocs"),values:e.gridPadding,onChange:o("gridPadding")}),(0,l.createElement)(p.__experimentalBoxControl,{label:(0,r.__)("Grid Margin","wedocs"),values:e.gridMargin,onChange:o("gridMargin")}),(0,l.createElement)(p.SelectControl,{label:(0,r.__)("Border Type","wedocs"),value:e.borderType,options:[{label:(0,r.__)("Solid","wedocs"),value:"solid"},{label:(0,r.__)("Dashed","wedocs"),value:"dashed"},{label:(0,r.__)("Dotted","wedocs"),value:"dotted"},{label:(0,r.__)("None","wedocs"),value:"none"}],onChange:e=>t({borderType:e})}),(0,l.createElement)(p.SelectControl,{label:(0,r.__)("Border Width","wedocs"),value:e.borderWidth,options:[{label:"0px",value:"0px"},{label:"1px",value:"1px"},{label:"2px",value:"2px"},{label:"3px",value:"3px"},{label:"4px",value:"4px"},{label:"5px",value:"5px"}],onChange:e=>t({borderWidth:e})}),(0,l.createElement)(p.SelectControl,{label:(0,r.__)("Border Radius","wedocs"),value:e.borderRadius,options:[{label:"0px",value:"0px"},{label:"4px",value:"4px"},{label:"8px",value:"8px"},{label:"12px",value:"12px"},{label:"16px",value:"16px"},{label:"20px",value:"20px"}],onChange:e=>t({borderRadius:e})})),(0,l.createElement)(p.PanelBody,{title:(0,r.__)("Button Styles","wedocs"),icon:"admin-appearance",initialOpen:!1},(0,l.createElement)("label",null,(0,r.__)("Button Colors","wedocs")),(0,l.createElement)(u.PanelColorSettings,{colors:a,colorSettings:[{value:e.buttonColor,label:(0,r.__)("Button Color","wedocs"),onChange:e=>o("buttonColor")(e)},{value:e.buttonHoverColor,label:(0,r.__)("Button Hover Color","wedocs"),onChange:e=>o("buttonHoverColor")(e)},{value:e.buttonTextColor,label:(0,r.__)("Button Text Color","wedocs"),onChange:e=>o("buttonTextColor")(e)},{value:e.buttonHoverTextColor,label:(0,r.__)("Button Hover Text Color","wedocs"),onChange:e=>o("buttonHoverTextColor")(e)}]}),(0,l.createElement)(p.__experimentalBoxControl,{label:(0,r.__)("Button Padding","wedocs"),values:e.buttonPadding,onChange:o("buttonPadding")}),(0,l.createElement)(p.__experimentalBoxControl,{label:(0,r.__)("Button Margin","wedocs"),values:e.buttonMargin,onChange:o("buttonMargin")}),(0,l.createElement)(p.SelectControl,{label:(0,r.__)("Button Border Radius","wedocs"),value:e.buttonBorderRadius,options:[{label:"0px",value:"0px"},{label:"4px",value:"4px"},{label:"8px",value:"8px"},{label:"12px",value:"12px"},{label:"16px",value:"16px"},{label:"20px",value:"20px"}],onChange:e=>t({buttonBorderRadius:e})}),(0,l.createElement)("div",{className:"wedocs-color-control"},(0,l.createElement)("label",null,(0,r.__)("Button Text","wedocs")),(0,l.createElement)(p.TextControl,{value:e.buttonText,onChange:o("buttonText")}))))},_=JSON.parse('{"UU":"wedocs/wedocs-docs-grid"}');(0,a.registerBlockType)(_.UU,{edit:({attributes:e,setAttributes:t})=>{const o=(0,u.useBlockProps)(),{useSelect:a}=wp.data,[n,i]=(0,c.useState)(1),[d,g]=(0,c.useState)(!1),{hideDocGrid:m,docStyle:b,docsPerPage:_,excludeDocs:v,order:C,orderBy:w,sectionsPerDoc:f,articlesPerSection:E,showDocArticle:x,keepArticlesCollapsed:y,showViewDetails:B,gridPadding:S,gridMargin:k,docTitleColor:F,docChildrenActiveColor:P,borderType:R,borderRadius:T,borderWidth:M,borderColor:N,buttonBorderRadius:D,buttonPadding:O,buttonMargin:$,buttonColor:L,buttonHoverColor:A,buttonTextColor:H,buttonText:j,buttonHoverTextColor:I}=e,V=[{label:"All",value:"all"},...Array.from({length:10},((e,t)=>({label:String(t+1),value:String(t+1)})))],W=[{label:(0,r.__)("weDocs Order","wedocs"),value:"menu_order"},{label:(0,r.__)("ID","wedocs"),value:"id"},{label:(0,r.__)("Name","wedocs"),value:"title"}],z=[{label:(0,r.__)("Ascending","wedocs"),value:"asc"},{label:(0,r.__)("Descending","wedocs"),value:"desc"}],U=[{label:"All",value:"all"},...Array.from({length:10},((e,t)=>({label:String(t+1),value:String(t+1)})))],{pages:G,sections:Y,articles:Z}=a((e=>{const{getEntityRecords:t}=e("core"),o=t("postType","docs",{status:"publish",per_page:-1,parent:0,orderby:w,order:C}),l=o?t("postType","docs",{status:"publish",parent_in:o.map((e=>e.id)),per_page:-1}):null,a=l?t("postType","docs",{status:"publish",parent_in:l.map((e=>e.id)),per_page:-1}):null;return{pages:o,sections:l,articles:a}}),[w,C]),q=(e=>{if("all"===_)return e;const t=parseInt(_),o=(n-1)*t,l=o+t;return e.slice(o,l)})((()=>{if(!G||!Y||!Z)return[];let e=[...G];return v&&v.length>0&&(e=e.filter((e=>!v.includes(e.id.toString())))),e=e.map((e=>{let t=Y.filter((t=>t.parent===e.id));"all"!==f&&(t=t.slice(0,parseInt(f))),t=t.map((e=>{let t=Z.filter((t=>t.parent===e.id));return"all"!==E&&(t=t.slice(0,parseInt(E))),{...e,articles:t}}));const o=t.reduce(((e,t)=>e+t.articles.length),0);return{...e,sections:t,articleCount:o}})),e})()),J=G?G.reduce(((e,t)=>(e[t.id]=t.title.rendered,e)),{}):{},K=(G&&G.map((e=>({value:e.id.toString(),label:e.title.rendered}))),e=>o=>{t({[e]:o})}),Q=v?v.map((e=>J[e]||e)):[];return(0,l.createElement)(c.Fragment,null,(0,l.createElement)(u.InspectorControls,null,(0,l.createElement)(p.PanelBody,{title:(0,r.__)("Doc Grid Settings","wedocs"),icon:s,initialOpen:!1},(0,l.createElement)(p.SelectControl,{value:b,options:[{label:"1x1",value:"1x1"},{label:"1x2",value:"1x2"}],label:(0,r.__)("DOCS GRID COLUMN STYLE","wedocs"),onChange:K("docStyle")}),(0,l.createElement)(p.SelectControl,{value:_,options:V,label:(0,r.__)("Docs per page","wedocs"),onChange:K("docsPerPage")}),(0,l.createElement)(p.FormTokenField,{value:Q,suggestions:Object.values(J),label:(0,r.__)("Exclude Docs","wedocs"),onChange:e=>{const o=e.map((e=>{const t=Object.entries(J).find((([t,o])=>o===e));return t?t[0]:e}));t({excludeDocs:o})}}),(0,l.createElement)(p.SelectControl,{value:C,options:z,label:(0,r.__)("Order","wedocs"),onChange:K("order")}),(0,l.createElement)(p.SelectControl,{value:w,options:W,label:(0,r.__)("Order by","wedocs"),onChange:K("orderBy")}),(0,l.createElement)(p.SelectControl,{value:f,options:U,label:(0,r.__)("Sections per doc","wedocs"),onChange:K("sectionsPerDoc")}),(0,l.createElement)(p.SelectControl,{value:E,options:U,label:(0,r.__)("Articles per section","wedocs"),onChange:K("articlesPerSection")}),(0,l.createElement)(p.PanelRow,null,(0,l.createElement)(p.ToggleControl,{checked:x,label:(0,r.__)("Show Doc Article","wedocs"),onChange:K("showDocArticle")})),(0,l.createElement)(p.PanelRow,null,(0,l.createElement)(p.ToggleControl,{checked:y,label:(0,r.__)("Keep Article Collapsed","wedocs"),onChange:K("keepArticlesCollapsed")})),(0,l.createElement)(p.PanelRow,null,(0,l.createElement)(p.ToggleControl,{checked:B,label:(0,r.__)("Show View Details Button","wedocs"),onChange:K("showViewDetails")})))),(0,l.createElement)(u.InspectorControls,null,(0,l.createElement)(h,{attributes:e,setAttributes:t})),(0,l.createElement)("div",{...o},m?(0,l.createElement)("div",{className:"backdrop"}):(0,l.createElement)("div",{className:"wedocs-block-wrapper"},(0,l.createElement)("div",{className:`wedocs-docs-grid wedocs-docs-grid--${b}`},d?(0,l.createElement)(Spinner,null):q.map((e=>((e,t)=>(0,l.createElement)("div",{key:e.id,className:"wedocs-docs-grid__item",style:t.item},(0,l.createElement)("h3",{className:"wedocs-docs-grid__title",style:t.title},e.title.rendered),((e,t)=>e.sections?(0,l.createElement)("div",{className:"wedocs-docs-grid__sections "+(y?"is-collapsed":"")},e.sections.map((e=>(0,l.createElement)("div",{key:e.id,className:"wedocs-docs-grid__section"},(0,l.createElement)("h4",{className:"wedocs-docs-grid__section-title",style:{...t.title,display:"flex",justifyContent:"space-between",alignItems:"center"}},(0,l.createElement)("span",null,e.title.rendered),x&&e.articles&&e.articles.length>0&&(0,l.createElement)("svg",{fill:"none",viewBox:"0 0 24 24",width:"16",strokeWidth:"2",stroke:"#acb8c4",className:y?"":"active"},(0,l.createElement)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 8.25l-7.5 7.5-7.5-7.5"}))),x&&!y&&e.articles&&(0,l.createElement)("ul",{className:"wedocs-docs-grid__articles"},e.articles.map((e=>(0,l.createElement)("li",{key:e.id,className:"wedocs-docs-grid__article",style:t.children},e.title.rendered))))))),0===e.sections.length&&(0,l.createElement)("span",{className:"inside"},(0,l.createElement)("svg",{fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor"},(0,l.createElement)("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"})),(0,r.__)("This document has no sections yet. Check back later or wait for the author to add content.","wedocs"))):null)(e,t),B&&(0,l.createElement)("div",{className:"wedocs-docs-grid__details"},(0,l.createElement)("span",{className:"wedocs-docs-grid__details-link",style:t.button},t.button.text))))(e,(()=>{const e=S?`${S.top} ${S.right} ${S.bottom} ${S.left}`:"",t=k?`${k.top} ${k.right} ${k.bottom} ${k.left}`:"",o=O?`${O.top} ${O.right} ${O.bottom} ${O.left}`:"",l=D||"8px",a=$?`${$.top} ${$.right} ${$.bottom} ${$.left}`:"";return{item:{padding:e,margin:t,borderStyle:R||"solid",borderWidth:M||"1px",borderColor:N||"rgba(0, 0, 0, 0.1)",borderRadius:T||"8px",backgroundColor:"#fff"},title:{color:F||"#1e1e1e"},children:{color:P||"#0073aa"},button:{padding:o,margin:a,backgroundColor:L||"#0073aa",color:H||"#ffffff",text:j||(0,r.__)("View Details","wedocs"),borderRadius:l||"8px","--hover-bg":A||"#005177","--hover-color":I||"#ffffff"}}})())))))))},save:()=>null})},609:e=>{e.exports=window.React}},o={};function l(e){var a=o[e];if(void 0!==a)return a.exports;var r=o[e]={exports:{}};return t[e](r,r.exports,l),r.exports}l.m=t,e=[],l.O=(t,o,a,r)=>{if(!o){var n=1/0;for(c=0;c<e.length;c++){o=e[c][0],a=e[c][1],r=e[c][2];for(var i=!0,d=0;d<o.length;d++)(!1&r||n>=r)&&Object.keys(l.O).every((e=>l.O[e](o[d])))?o.splice(d--,1):(i=!1,r<n&&(n=r));if(i){e.splice(c--,1);var s=a();void 0!==s&&(t=s)}}return t}r=r||0;for(var c=e.length;c>0&&e[c-1][2]>r;c--)e[c]=e[c-1];e[c]=[o,a,r]},l.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),(()=>{var e={366:0,337:0};l.O.j=t=>0===e[t];var t=(t,o)=>{var a,r,n=o[0],i=o[1],d=o[2],s=0;if(n.some((t=>0!==e[t]))){for(a in i)l.o(i,a)&&(l.m[a]=i[a]);if(d)var c=d(l)}for(t&&t(o);s<n.length;s++)r=n[s],l.o(e,r)&&e[r]&&e[r][0](),e[r]=0;return l.O(c)},o=self.webpackChunkweDocs=self.webpackChunkweDocs||[];o.forEach(t.bind(null,0)),o.push=t.bind(null,o.push.bind(o))})();var a=l.O(void 0,[337],(()=>l(445)));a=l.O(a)})(); No newline at end of file
(()=>{"use strict";var e,o={684:(e,o,a)=>{a.d(o,{A:()=>n});var t=a(5573),l=a(790);const n=(0,l.jsx)(t.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,l.jsx)(t.Path,{fillRule:"evenodd",d:"M10.289 4.836A1 1 0 0111.275 4h1.306a1 1 0 01.987.836l.244 1.466c.787.26 1.503.679 2.108 1.218l1.393-.522a1 1 0 011.216.437l.653 1.13a1 1 0 01-.23 1.273l-1.148.944a6.025 6.025 0 010 2.435l1.149.946a1 1 0 01.23 1.272l-.653 1.13a1 1 0 01-1.216.437l-1.394-.522c-.605.54-1.32.958-2.108 1.218l-.244 1.466a1 1 0 01-.987.836h-1.306a1 1 0 01-.986-.836l-.244-1.466a5.995 5.995 0 01-2.108-1.218l-1.394.522a1 1 0 01-1.217-.436l-.653-1.131a1 1 0 01.23-1.272l1.149-.946a6.026 6.026 0 010-2.435l-1.148-.944a1 1 0 01-.23-1.272l.653-1.131a1 1 0 011.217-.437l1.393.522a5.994 5.994 0 012.108-1.218l.244-1.466zM14.929 12a3 3 0 11-6 0 3 3 0 016 0z",clipRule:"evenodd"})})},790:e=>{e.exports=window.ReactJSXRuntime},2317:(e,o,a)=>{var t=a(4997),l=a(7723),n=a(4715),r=a(6427),i=a(6087),s=(a(7143),a(790));const d=({attributes:e,setAttributes:o})=>(0,s.jsxs)(r.PanelBody,{title:(0,l.__)("List Items","dynamic-table-of-contents-block-wp"),initialOpen:!1,children:[(0,s.jsx)("h4",{children:(0,l.__)("TOC Container","dynamic-table-of-contents-block-wp")}),(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)("label",{children:(0,l.__)("Background Color","dynamic-table-of-contents-block-wp")}),(0,s.jsx)(r.ColorPicker,{color:containerBackgroundColor,onChange:e=>o({containerBackgroundColor:e})})]})]}),c=({attributes:e,setAttributes:o})=>(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.InspectorControls,{children:(0,s.jsxs)(r.PanelBody,{title:(0,l.__)("General","dynamic-table-of-contents-block-wp"),initialOpen:!0,children:[(0,s.jsx)(r.TextControl,{label:(0,l.__)("TOC Title","dynamic-table-of-contents-block-wp"),value:tocTitle,onChange:e=>o({tocTitle:e})}),(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)("label",{style:{fontWeight:"600",marginBottom:"8px",display:"block"},children:(0,l.__)("Supported Heading Tags","dynamic-table-of-contents-block-wp")}),["h1","h2","h3","h4","h5"].map(e=>(0,s.jsx)(r.CheckboxControl,{label:e.toUpperCase(),checked:supportedHeadings.includes(e),onChange:a=>{const t=a?[...supportedHeadings,e]:supportedHeadings.filter(o=>o!==e);o({supportedHeadings:t})}},e))]}),(0,s.jsx)(r.ToggleControl,{label:(0,l.__)("List Hierarchy","dynamic-table-of-contents-block-wp"),help:(0,l.__)("Indent subheadings to show hierarchy","dynamic-table-of-contents-block-wp"),checked:showHierarchy,onChange:e=>o({showHierarchy:e})}),(0,s.jsx)(r.ToggleControl,{label:(0,l.__)("List Numbering","dynamic-table-of-contents-block-wp"),help:(0,l.__)("Show numbered list instead of bullets","dynamic-table-of-contents-block-wp"),checked:showNumbering,onChange:e=>o({showNumbering:e})}),(0,s.jsx)(r.ToggleControl,{label:(0,l.__)("Collapsible on Small Devices","dynamic-table-of-contents-block-wp"),help:(0,l.__)("Make TOC collapsible on mobile devices","dynamic-table-of-contents-block-wp"),checked:collapsibleOnMobile,onChange:e=>o({collapsibleOnMobile:e})}),(0,s.jsx)(r.ToggleControl,{label:(0,l.__)("Smooth Scroll Behavior","dynamic-table-of-contents-block-wp"),checked:smoothScroll,onChange:e=>o({smoothScroll:e})}),(0,s.jsx)(r.ToggleControl,{label:(0,l.__)("Sticky Mode","dynamic-table-of-contents-block-wp"),help:(0,l.__)("Keep TOC fixed while scrolling","dynamic-table-of-contents-block-wp"),checked:stickyMode,onChange:e=>o({stickyMode:e})})]})}),(0,s.jsxs)(n.InspectorControls,{group:"styles",children:[(0,s.jsx)(d,{attributes:e,setAttributes:o}),(0,s.jsxs)(r.PanelBody,{title:(0,l.__)("Style","dynamic-table-of-contents-block-wp"),initialOpen:!1,children:[(0,s.jsx)("h4",{children:(0,l.__)("TOC Container","dynamic-table-of-contents-block-wp")}),(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)("label",{children:(0,l.__)("Background Color","dynamic-table-of-contents-block-wp")}),(0,s.jsx)(r.ColorPicker,{color:containerBackgroundColor,onChange:e=>o({containerBackgroundColor:e})})]}),(0,s.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Width","dynamic-table-of-contents-block-wp"),value:containerWidth,onChange:e=>o({containerWidth:e}),units:[{value:"%",label:"%"},{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}]}),(0,s.jsx)(r.__experimentalBoxControl,{label:(0,l.__)("Padding","dynamic-table-of-contents-block-wp"),values:containerPadding,onChange:e=>o({containerPadding:e})}),(0,s.jsx)(r.__experimentalBoxControl,{label:(0,l.__)("Margin","dynamic-table-of-contents-block-wp"),values:containerMargin,onChange:e=>o({containerMargin:e})}),(0,s.jsx)(r.SelectControl,{label:(0,l.__)("Border Style","dynamic-table-of-contents-block-wp"),value:containerBorderStyle,options:[{label:(0,l.__)("None","dynamic-table-of-contents-block-wp"),value:"none"},{label:(0,l.__)("Solid","dynamic-table-of-contents-block-wp"),value:"solid"},{label:(0,l.__)("Dashed","dynamic-table-of-contents-block-wp"),value:"dashed"},{label:(0,l.__)("Dotted","dynamic-table-of-contents-block-wp"),value:"dotted"}],onChange:e=>o({containerBorderStyle:e})}),"none"!==containerBorderStyle&&(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Border Width","dynamic-table-of-contents-block-wp"),value:containerBorderWidth,onChange:e=>o({containerBorderWidth:e})}),(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)("label",{children:(0,l.__)("Border Color","dynamic-table-of-contents-block-wp")}),(0,s.jsx)(r.ColorPicker,{color:containerBorderColor,onChange:e=>o({containerBorderColor:e})})]})]}),(0,s.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Border Radius","dynamic-table-of-contents-block-wp"),value:containerBorderRadius,onChange:e=>o({containerBorderRadius:e})}),(0,s.jsx)("hr",{style:{margin:"20px 0"}}),(0,s.jsx)("h4",{children:(0,l.__)("TOC Title","dynamic-table-of-contents-block-wp")}),(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)("label",{children:(0,l.__)("Color","dynamic-table-of-contents-block-wp")}),(0,s.jsx)(r.ColorPicker,{color:titleColor,onChange:e=>o({titleColor:e})})]}),(0,s.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Font Size","dynamic-table-of-contents-block-wp"),value:titleFontSize,onChange:e=>o({titleFontSize:e})}),(0,s.jsx)(r.SelectControl,{label:(0,l.__)("Font Weight","dynamic-table-of-contents-block-wp"),value:titleFontWeight,options:[{label:"300",value:"300"},{label:"400",value:"400"},{label:"500",value:"500"},{label:"600",value:"600"},{label:"700",value:"700"},{label:"800",value:"800"}],onChange:e=>o({titleFontWeight:e})}),(0,s.jsx)("hr",{style:{margin:"20px 0"}}),(0,s.jsx)("h4",{children:(0,l.__)("TOC List","dynamic-table-of-contents-block-wp")}),(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)("label",{children:(0,l.__)("Color","dynamic-table-of-contents-block-wp")}),(0,s.jsx)(r.ColorPicker,{color:listColor,onChange:e=>o({listColor:e})})]}),(0,s.jsxs)("div",{style:{marginBottom:"20px"},children:[(0,s.jsx)("label",{children:(0,l.__)("Hover Color","dynamic-table-of-contents-block-wp")}),(0,s.jsx)(r.ColorPicker,{color:listHoverColor,onChange:e=>o({listHoverColor:e})})]}),(0,s.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Font Size","dynamic-table-of-contents-block-wp"),value:listFontSize,onChange:e=>o({listFontSize:e})})]})]})]}),p=JSON.parse('{"UU":"wedocs/table-of-contents"}');(0,t.registerBlockType)(p.UU,{edit:function({attributes:e,setAttributes:o,clientId:a}){const{blockId:t,tocTitle:r,supportedHeadings:d,showHierarchy:p,showNumbering:h,collapsibleOnMobile:g,containerBackgroundColor:u,containerWidth:b,containerPadding:x,containerMargin:m,containerBorderStyle:_,containerBorderWidth:v,containerBorderColor:C,containerBorderRadius:w,titleColor:y,titleFontSize:f,titleFontWeight:j,titlePadding:S,listColor:B,listHoverColor:T,listFontSize:k,smoothScroll:P,stickyMode:$,additionalCssClass:F}=e,[M,R]=(0,i.useState)([]);(0,i.useEffect)(()=>{t||o({blockId:`toc-${a}`})},[t,a,o]),(0,i.useEffect)(()=>{const e=[{level:2,text:"Introduction",id:"introduction"},{level:3,text:"Getting Started",id:"getting-started"},{level:3,text:"Basic Features",id:"basic-features"},{level:2,text:"Advanced Usage",id:"advanced-usage"},{level:3,text:"Configuration",id:"configuration"},{level:4,text:"Settings Panel",id:"settings-panel"},{level:2,text:"Conclusion",id:"conclusion"}].filter(e=>d.includes(`h${e.level}`));R(e)},[d]);const D=(0,n.useBlockProps)({className:`${F} ${$?"sticky-mode":""}`.trim(),"data-block-id":t,style:{"--list-item-sytle":u,width:b,padding:x?`${x.top} ${x.right} ${x.bottom} ${x.left}`:void 0,margin:m?`${m.top} ${m.right} ${m.bottom} ${m.left}`:void 0,borderStyle:"none"!==_?_:void 0,borderWidth:"none"!==_?v:void 0,borderColor:"none"!==_?C:void 0,borderRadius:w}});return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(c,{attributes:e,setAttributes:o}),(0,s.jsxs)("div",{...D,children:[(0,s.jsx)("div",{className:"toc-title",style:{color:y,fontSize:f,fontWeight:j,padding:S?`${S.top} ${S.right} ${S.bottom} ${S.left}`:void 0},children:r}),(0,s.jsx)("div",{className:"toc-content",style:{color:B,fontSize:k},children:((e,o,a)=>{if(0===e.length)return(0,s.jsx)("div",{className:"toc-empty-state",children:(0,s.jsx)("p",{children:(0,l.__)("No headings found. Add some headings to your content to see them here.","dynamic-table-of-contents-block-wp")})});let t=1;const n={2:0,3:0,4:0,5:0};return(0,s.jsx)("ul",{className:`toc-list ${o?"hierarchical":"flat"} ${a?"numbered":"bulleted"}`,children:e.map((e,l)=>{if(a)if(o){n[e.level]++;for(let o=e.level+1;o<=5;o++)n[o]=0}else n[e.level]=t++;const r=o?20*(e.level-2):0,i=a?o?Object.entries(n).slice(0,e.level-1).map(([e,o])=>o>0?o:"").filter(e=>e).join("."):n[e.level]:"";return(0,s.jsx)("li",{style:{marginLeft:`${r}px`},children:(0,s.jsxs)("a",{href:`#${e.id}`,className:"toc-link",children:[a&&(0,s.jsxs)("span",{className:"toc-number",children:[i,". "]}),e.text]})},l)})})})(M,p,h)}),g&&(0,s.jsx)("div",{className:"toc-mobile-notice",style:{marginTop:"10px",fontSize:"12px",opacity:.7},children:(0,l.__)("(Collapsible on mobile devices)","dynamic-table-of-contents-block-wp")})]})]})}})},4715:e=>{e.exports=window.wp.blockEditor},4997:e=>{e.exports=window.wp.blocks},5573:e=>{e.exports=window.wp.primitives},6087:e=>{e.exports=window.wp.element},6239:(e,o,a)=>{var t=a(4997),l=a(7723),n=a(4715),r=a(6427),i=a(6087),s=a(7143);const d=window.wp.coreData;var c=a(790);const p=({children:e,defaultTab:o="setup"})=>{const[a,t]=(0,i.useState)(o),n=[{key:"setup",label:(0,l.__)("Setup","wedocs"),icon:"admin-settings"},{key:"style",label:(0,l.__)("Style","wedocs"),icon:"admin-appearance"}];return(0,c.jsxs)("div",{className:"contributors-tab-system",children:[(0,c.jsx)("div",{style:{borderBottom:"1px solid #ddd",marginBottom:"16px",paddingBottom:"8px"},children:(0,c.jsx)(r.ButtonGroup,{children:n.map(e=>(0,c.jsxs)(r.Button,{variant:a===e.key?"primary":"secondary",onClick:()=>t(e.key),style:{marginRight:"4px",display:"flex",alignItems:"center",gap:"4px"},children:[(0,c.jsx)("span",{className:`dashicons dashicons-${e.icon}`,style:{fontSize:"16px"}}),e.label]},e.key))})}),(0,c.jsx)("div",{className:"tab-content",children:e.map((e,o)=>{const t=0===o?"setup":"style";return(0,c.jsx)("div",{style:{display:a===t?"block":"none"},children:e},t)})})]})},h=({label:e,value:o={},onChange:a,colorValue:t,onColorChange:i,hoverColorValue:s,onHoverColorChange:d,showHoverColor:p=!0,showLineHeight:h=!0,showLetterSpacing:g=!0,showTextTransform:u=!0,showTextDecoration:b=!0})=>{const x=(e,t)=>{a({...o,[e]:t})};return(0,c.jsxs)(r.PanelBody,{title:e,initialOpen:!1,children:[(0,c.jsx)(n.PanelColorSettings,{title:(0,l.__)("Colors","wedocs"),colorSettings:[{value:t,onChange:i,label:(0,l.__)("Text Color","wedocs")},...p?[{value:s,onChange:d,label:(0,l.__)("Hover Color","wedocs")}]:[]]}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4}),(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Font Family","wedocs"),value:o.fontFamily||"default",options:[{label:(0,l.__)("Default","wedocs"),value:"default"},{label:"Arial",value:"Arial, sans-serif"},{label:"Georgia",value:"Georgia, serif"},{label:"Helvetica",value:"Helvetica, sans-serif"},{label:"Times New Roman",value:'"Times New Roman", serif'},{label:"Verdana",value:"Verdana, sans-serif"},{label:"Roboto",value:"Roboto, sans-serif"},{label:"Open Sans",value:'"Open Sans", sans-serif'},{label:"Lato",value:"Lato, sans-serif"},{label:"Montserrat",value:"Montserrat, sans-serif"}],onChange:e=>x("fontFamily","default"===e?void 0:e)}),(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Font Size","wedocs"),value:o.fontSize||"14px",onChange:e=>x("fontSize",e),units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"},{value:"%",label:"%"}]}),(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Font Weight","wedocs"),value:o.fontWeight||"400",options:[{label:(0,l.__)("100 - Thin","wedocs"),value:"100"},{label:(0,l.__)("200 - Extra Light","wedocs"),value:"200"},{label:(0,l.__)("300 - Light","wedocs"),value:"300"},{label:(0,l.__)("400 - Normal","wedocs"),value:"400"},{label:(0,l.__)("500 - Medium","wedocs"),value:"500"},{label:(0,l.__)("600 - Semi Bold","wedocs"),value:"600"},{label:(0,l.__)("700 - Bold","wedocs"),value:"700"},{label:(0,l.__)("800 - Extra Bold","wedocs"),value:"800"},{label:(0,l.__)("900 - Black","wedocs"),value:"900"}],onChange:e=>x("fontWeight",e)}),(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Font Style","wedocs"),value:o.fontStyle||"normal",options:[{label:(0,l.__)("Normal","wedocs"),value:"normal"},{label:(0,l.__)("Italic","wedocs"),value:"italic"},{label:(0,l.__)("Oblique","wedocs"),value:"oblique"}],onChange:e=>x("fontStyle",e)}),h&&(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Line Height","wedocs"),value:o.lineHeight||"normal",onChange:e=>x("lineHeight",e),units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"",label:"unitless"}]}),g&&(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Letter Spacing","wedocs"),value:o.letterSpacing||"normal",onChange:e=>x("letterSpacing",e),units:[{value:"px",label:"px"},{value:"em",label:"em"}]}),u&&(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Text Transform","wedocs"),value:o.textTransform||"none",options:[{label:(0,l.__)("None","wedocs"),value:"none"},{label:(0,l.__)("Uppercase","wedocs"),value:"uppercase"},{label:(0,l.__)("Lowercase","wedocs"),value:"lowercase"},{label:(0,l.__)("Capitalize","wedocs"),value:"capitalize"}],onChange:e=>x("textTransform",e)}),b&&(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Text Decoration","wedocs"),value:o.textDecoration||"none",options:[{label:(0,l.__)("None","wedocs"),value:"none"},{label:(0,l.__)("Underline","wedocs"),value:"underline"},{label:(0,l.__)("Overline","wedocs"),value:"overline"},{label:(0,l.__)("Line Through","wedocs"),value:"line-through"}],onChange:e=>x("textDecoration",e)})]})},g=({label:e,paddingValue:o={},onPaddingChange:a,marginValue:t={},onMarginChange:n,showPadding:i=!0,showMargin:s=!0,showGap:d=!1,gapValue:p,onGapChange:h})=>(0,c.jsxs)(r.PanelBody,{title:e,initialOpen:!1,children:[i&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.__experimentalBoxControl,{label:(0,l.__)("Padding","wedocs"),values:o,onChange:a,units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"},{value:"%",label:"%"}],allowReset:!0,resetValues:{top:"0px",right:"0px",bottom:"0px",left:"0px"}}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4})]}),s&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.__experimentalBoxControl,{label:(0,l.__)("Margin","wedocs"),values:t,onChange:n,units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"},{value:"%",label:"%"}],allowReset:!0,resetValues:{top:"0px",right:"0px",bottom:"0px",left:"0px"}}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4})]}),d&&(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Gap","wedocs"),value:p||"10px",onChange:h,units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}]})]}),u=({label:e,borderStyle:o="none",onBorderStyleChange:a,borderWidth:t={},onBorderWidthChange:i,borderColor:s,onBorderColorChange:d,borderRadius:p,onBorderRadiusChange:h,showIndividualSides:g=!0})=>(0,c.jsxs)(r.PanelBody,{title:e,initialOpen:!1,children:[(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Border Style","wedocs"),value:o,options:[{label:(0,l.__)("None","wedocs"),value:"none"},{label:(0,l.__)("Solid","wedocs"),value:"solid"},{label:(0,l.__)("Dashed","wedocs"),value:"dashed"},{label:(0,l.__)("Dotted","wedocs"),value:"dotted"},{label:(0,l.__)("Double","wedocs"),value:"double"},{label:(0,l.__)("Groove","wedocs"),value:"groove"},{label:(0,l.__)("Ridge","wedocs"),value:"ridge"},{label:(0,l.__)("Inset","wedocs"),value:"inset"},{label:(0,l.__)("Outset","wedocs"),value:"outset"}],onChange:a}),"none"!==o&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4}),g?(0,c.jsx)(r.__experimentalBoxControl,{label:(0,l.__)("Border Width","wedocs"),values:t,onChange:i,units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}],allowReset:!0,resetValues:{top:"1px",right:"1px",bottom:"1px",left:"1px"}}):(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Border Width","wedocs"),value:t.top||"1px",onChange:e=>i({top:e,right:e,bottom:e,left:e}),units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}]}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4}),(0,c.jsx)(n.PanelColorSettings,{title:(0,l.__)("Border Color","wedocs"),colorSettings:[{value:s,onChange:d,label:(0,l.__)("Color","wedocs")}]})]}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4}),(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Border Radius","wedocs"),value:p||"0px",onChange:h,units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"},{value:"%",label:"%"}]})]}),b=({label:e,backgroundType:o="classic",onBackgroundTypeChange:a,backgroundColor:t,onBackgroundColorChange:i,backgroundGradient:s,onBackgroundGradientChange:d,backgroundImage:p={},onBackgroundImageChange:h,showGradient:g=!0,showImage:u=!0})=>(0,c.jsxs)(r.PanelBody,{title:e,initialOpen:!1,children:[(0,c.jsx)(r.RadioControl,{label:(0,l.__)("Background Type","wedocs"),selected:o,options:[{label:(0,l.__)("Classic","wedocs"),value:"classic"},...g?[{label:(0,l.__)("Gradient","wedocs"),value:"gradient"}]:[]],onChange:a}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4}),"classic"===o&&(0,c.jsx)(n.PanelColorSettings,{title:(0,l.__)("Background Color","wedocs"),colorSettings:[{value:t,onChange:i,label:(0,l.__)("Color","wedocs")}]}),"gradient"===o&&g&&(0,c.jsx)(r.TextControl,{label:(0,l.__)("Gradient CSS","wedocs"),value:s||"",onChange:d,placeholder:"linear-gradient(45deg, #ff0000, #00ff00)",help:(0,l.__)("Enter CSS gradient value","wedocs")}),u&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4}),(0,c.jsxs)("div",{children:[(0,c.jsx)("h4",{children:(0,l.__)("Background Image","wedocs")}),(0,c.jsx)(n.MediaUploadCheck,{children:(0,c.jsx)(n.MediaUpload,{onSelect:e=>h({url:e.url,alt:e.alt,id:e.id}),allowedTypes:["image"],value:p?.id,render:({open:e})=>(0,c.jsx)(r.Button,{onClick:e,variant:"secondary",children:p?.url?(0,l.__)("Change Image","wedocs"):(0,l.__)("Select Image","wedocs")})})}),p?.url&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.__experimentalSpacer,{marginTop:2,marginBottom:2}),(0,c.jsx)(r.Button,{onClick:()=>h({url:"",alt:"",id:""}),variant:"secondary",isDestructive:!0,children:(0,l.__)("Remove Image","wedocs")})]})]})]})]}),x=({label:e,shadowValue:o={},onShadowChange:a,showToggle:t=!0})=>{var i;const s=(e,t)=>{a({...o,[e]:t})},d=null!==(i=o.enabled)&&void 0!==i&&i;return(0,c.jsxs)(r.PanelBody,{title:e,initialOpen:!1,children:[t&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.ToggleControl,{label:(0,l.__)("Enable Box Shadow","wedocs"),checked:d,onChange:e=>s("enabled",e)}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4})]}),(d||!t)&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Horizontal Offset","wedocs"),value:o.horizontal||"0px",onChange:e=>s("horizontal",e),units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}]}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:3,marginBottom:3}),(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Vertical Offset","wedocs"),value:o.vertical||"2px",onChange:e=>s("vertical",e),units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}]}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:3,marginBottom:3}),(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Blur Radius","wedocs"),value:o.blur||"4px",onChange:e=>s("blur",e),units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}]}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:3,marginBottom:3}),(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Spread Radius","wedocs"),value:o.spread||"0px",onChange:e=>s("spread",e),units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"}]}),(0,c.jsx)(r.__experimentalSpacer,{marginTop:4,marginBottom:4}),(0,c.jsx)(n.PanelColorSettings,{title:(0,l.__)("Shadow Color","wedocs"),colorSettings:[{value:o.color||"rgba(0,0,0,0.1)",onChange:e=>s("color",e),label:(0,l.__)("Color","wedocs")}]})]})]})},m=({label:e,widthValue:o,onWidthChange:a,heightValue:t,onHeightChange:n,showHeight:i=!0,linkValues:s=!1})=>(0,c.jsxs)(r.PanelBody,{title:e,initialOpen:!1,children:[(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Width","wedocs"),value:o||"auto",onChange:e=>{a(e),s&&i&&n&&n(e)},units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"},{value:"%",label:"%"},{value:"auto",label:"auto"}]}),i&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.__experimentalSpacer,{marginTop:3,marginBottom:3}),(0,c.jsx)(r.__experimentalUnitControl,{label:(0,l.__)("Height","wedocs"),value:t||"auto",onChange:n,units:[{value:"px",label:"px"},{value:"em",label:"em"},{value:"rem",label:"rem"},{value:"%",label:"%"},{value:"auto",label:"auto"}]})]})]}),_=a.p+"images/avatar_1.png",v=(a.p,e=>{const{attributes:o,setAttributes:a}=e,[t,v]=(0,i.useState)([]),[C,w]=(0,i.useState)(!1),[y,f]=(0,i.useState)([]),[j,S]=(0,i.useState)(!1),B=window.weDocsAdminScriptVars?.isPro||!1,T=(0,n.useBlockProps)({className:`wedocs-contributors ${o.additionalCssClass}`,style:{backgroundColor:"classic"===o.backgroundType?o.backgroundColor:void 0,backgroundImage:"gradient"===o.backgroundType?o.backgroundGradient:o.backgroundImage?.url?`url(${o.backgroundImage.url})`:void 0,padding:`${o.padding.top} ${o.padding.right} ${o.padding.bottom} ${o.padding.left}`,margin:`${o.margin.top} ${o.margin.right} ${o.margin.bottom} ${o.margin.left}`,borderStyle:"none"!==o.borderStyle?o.borderStyle:void 0,borderWidth:"none"!==o.borderStyle?`${o.borderWidth.top} ${o.borderWidth.right} ${o.borderWidth.bottom} ${o.borderWidth.left}`:void 0,borderColor:"none"!==o.borderStyle?o.borderColor:void 0,borderRadius:o.borderRadius,boxShadow:o.boxShadow.enabled?`${o.boxShadow.horizontal} ${o.boxShadow.vertical} ${o.boxShadow.blur} ${o.boxShadow.spread} ${o.boxShadow.color}`:void 0}}),k=(0,s.useSelect)(e=>{const{getCurrentPostId:o,getCurrentPostType:a}=e("core/editor")||{};return o?e(d.store).getEntityRecord("postType",a(),o()):null},[]);return(0,i.useEffect)(()=>{"manual"===o.contributorDisplayMode&&(w(!0),wp.apiFetch({path:"/wp/v2/users?per_page=100&context=edit"}).then(e=>{v(e),w(!1)}).catch(()=>{w(!1)}))},[o.contributorDisplayMode]),(0,i.useEffect)(()=>{k&&(async()=>{S(!0);try{const e=[];switch(o.contributorDisplayMode){case"main_author":if(k.author){const o=await wp.apiFetch({path:`/wp/v2/users/${k.author}?context=edit`});o&&e.push(o)}break;case"manual":if(o.selectedContributors.length>0)for(const a of o.selectedContributors)try{const o=await wp.apiFetch({path:`/wp/v2/users/${a}?context=edit`});o&&e.push(o)}catch(e){console.warn(`Could not fetch user ${a}:`,e)}break;default:if(k.author){const o=await wp.apiFetch({path:`/wp/v2/users/${k.author}?context=edit`});o&&e.push(o)}if(k.id)try{const o=await wp.apiFetch({path:`/wp/v2/${k.type}/${k.id}/revisions?per_page=50`}),a=[k.author];for(const t of o)if(t.author&&!a.includes(t.author)){a.push(t.author);try{const o=await wp.apiFetch({path:`/wp/v2/users/${t.author}?context=edit`});o&&e.push(o)}catch(e){console.warn(`Could not fetch revision author ${t.author}:`,e)}}}catch(e){console.warn("Could not fetch revisions:",e)}}f(e)}catch(e){console.error("Error fetching contributors:",e),f([])}finally{S(!1)}})()},[k,o.contributorDisplayMode,o.selectedContributors]),B?(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(n.InspectorControls,{children:(0,c.jsxs)(p,{defaultTab:"setup",children:[(0,c.jsxs)(c.Fragment,{children:[(0,c.jsxs)(r.PanelBody,{title:(0,l.__)("General Settings","wedocs"),initialOpen:!0,children:[(0,c.jsx)(r.ToggleControl,{label:(0,l.__)("Show Title","wedocs"),checked:o.showTitle,onChange:e=>a({showTitle:e})}),o.showTitle&&(0,c.jsx)(r.TextControl,{label:(0,l.__)("Title","wedocs"),value:o.title,onChange:e=>a({title:e})}),(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Contributor Display","wedocs"),value:o.contributorDisplayMode,options:[{label:(0,l.__)("Show all contributors","wedocs"),value:"all"},{label:(0,l.__)("Manually select contributors","wedocs"),value:"manual"},{label:(0,l.__)("Show only main author","wedocs"),value:"main_author"}],onChange:e=>a({contributorDisplayMode:e})}),"manual"===o.contributorDisplayMode&&(0,c.jsxs)("div",{children:[(0,c.jsx)("h4",{children:(0,l.__)("Select Contributors","wedocs")}),C?(0,c.jsx)(r.Spinner,{}):(0,c.jsx)("div",{style:{maxHeight:"200px",overflowY:"auto",border:"1px solid #ddd",padding:"10px"},children:t.map(e=>(0,c.jsxs)("label",{style:{display:"block",marginBottom:"5px"},children:[(0,c.jsx)("input",{type:"checkbox",checked:o.selectedContributors.includes(e.id),onChange:t=>{const l=t.target.checked?[...o.selectedContributors,e.id]:o.selectedContributors.filter(o=>o!==e.id);a({selectedContributors:l})},style:{marginRight:"8px"}}),e.name]},e.id))})]})]}),(0,c.jsxs)(r.PanelBody,{title:(0,l.__)("Avatar Settings","wedocs"),initialOpen:!1,children:[(0,c.jsx)(r.ToggleControl,{label:(0,l.__)("Show Avatar","wedocs"),checked:o.showAvatar,onChange:e=>a({showAvatar:e})}),o.showAvatar&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.RadioControl,{label:(0,l.__)("Avatar Type","wedocs"),selected:o.avatarType,options:[{label:(0,l.__)("User Avatar","wedocs"),value:"user_avatar"},{label:(0,l.__)("Common Icon","wedocs"),value:"common_icon"}],onChange:e=>a({avatarType:e})}),(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Avatar Shape","wedocs"),value:o.avatarShape,options:[{label:(0,l.__)("Circle","wedocs"),value:"circle"},{label:(0,l.__)("Rounded","wedocs"),value:"rounded"},{label:(0,l.__)("Square","wedocs"),value:"square"}],onChange:e=>a({avatarShape:e})}),(0,c.jsx)(r.ToggleControl,{label:(0,l.__)("Hover Effect","wedocs"),checked:o.avatarHoverEffect,onChange:e=>a({avatarHoverEffect:e})})]})]}),(0,c.jsxs)(r.PanelBody,{title:(0,l.__)("Date Settings","wedocs"),initialOpen:!1,children:[(0,c.jsx)(r.ToggleControl,{label:(0,l.__)("Show Last Updated Date","wedocs"),checked:o.showLastUpdated,onChange:e=>a({showLastUpdated:e})}),o.showLastUpdated&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(r.RadioControl,{label:(0,l.__)("Date Format","wedocs"),selected:o.dateFormat,options:[{label:(0,l.__)("WordPress Default","wedocs"),value:"wp_default"},{label:(0,l.__)("Custom Format","wedocs"),value:"custom"}],onChange:e=>a({dateFormat:e})}),"custom"===o.dateFormat&&(0,c.jsx)(r.TextControl,{label:(0,l.__)("Custom Date Format","wedocs"),value:o.customDateFormat,onChange:e=>a({customDateFormat:e}),help:(0,l.__)('Use PHP date format. E.g., F j, Y for "January 1, 2023"',"wedocs")}),(0,c.jsx)(r.TextControl,{label:(0,l.__)("Date Prefix Text","wedocs"),value:o.datePrefix,onChange:e=>a({datePrefix:e})})]})]}),(0,c.jsxs)(r.PanelBody,{title:(0,l.__)("Advanced","wedocs"),initialOpen:!1,children:[(0,c.jsx)(r.TextControl,{label:(0,l.__)("Additional CSS Classes","wedocs"),value:o.additionalCssClass,onChange:e=>a({additionalCssClass:e}),help:(0,l.__)("Separate multiple classes with spaces","wedocs")}),(0,c.jsx)(r.ToggleControl,{label:(0,l.__)("Enable Schema Markup","wedocs"),checked:o.enableSchema,onChange:e=>a({enableSchema:e}),help:(0,l.__)("Output structured data for author and dateModified","wedocs")}),(0,c.jsx)(r.SelectControl,{label:(0,l.__)("Avatar Link Behavior","wedocs"),value:o.linkBehavior,options:[{label:(0,l.__)("Link to user profile","wedocs"),value:"user_profile"},{label:(0,l.__)("No link","wedocs"),value:"no_link"},{label:(0,l.__)("Custom link","wedocs"),value:"custom_link"}],onChange:e=>a({linkBehavior:e})}),"custom_link"===o.linkBehavior&&(0,c.jsx)(r.TextControl,{label:(0,l.__)("Custom Link URL","wedocs"),value:o.customLinkUrl,onChange:e=>a({customLinkUrl:e}),placeholder:"https://example.com/author"})]})]}),(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(b,{label:(0,l.__)("Container Background","wedocs"),backgroundType:o.backgroundType,onBackgroundTypeChange:e=>a({backgroundType:e}),backgroundColor:o.backgroundColor,onBackgroundColorChange:e=>a({backgroundColor:e}),backgroundGradient:o.backgroundGradient,onBackgroundGradientChange:e=>a({backgroundGradient:e}),backgroundImage:o.backgroundImage,onBackgroundImageChange:e=>a({backgroundImage:e})}),(0,c.jsx)(g,{label:(0,l.__)("Container Spacing","wedocs"),paddingValue:o.padding,onPaddingChange:e=>a({padding:e}),marginValue:o.margin,onMarginChange:e=>a({margin:e}),showGap:!0,gapValue:o.contributorGap,onGapChange:e=>a({contributorGap:e})}),(0,c.jsx)(u,{label:(0,l.__)("Container Border","wedocs"),borderStyle:o.borderStyle,onBorderStyleChange:e=>a({borderStyle:e}),borderWidth:o.borderWidth,onBorderWidthChange:e=>a({borderWidth:e}),borderColor:o.borderColor,onBorderColorChange:e=>a({borderColor:e}),borderRadius:o.borderRadius,onBorderRadiusChange:e=>a({borderRadius:e})}),(0,c.jsx)(x,{label:(0,l.__)("Container Shadow","wedocs"),shadowValue:o.boxShadow,onShadowChange:e=>a({boxShadow:e})}),o.showTitle&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(h,{label:(0,l.__)("Title Typography","wedocs"),value:o.contributorTitleTypography,onChange:e=>a({contributorTitleTypography:e}),colorValue:o.contributorTitleColor,onColorChange:e=>a({contributorTitleColor:e}),hoverColorValue:o.contributorTitleHoverColor,onHoverColorChange:e=>a({contributorTitleHoverColor:e})}),(0,c.jsx)(g,{label:(0,l.__)("Title Spacing","wedocs"),paddingValue:o.titlePadding,onPaddingChange:e=>a({titlePadding:e}),marginValue:o.titleMargin,onMarginChange:e=>a({titleMargin:e}),showGap:!1})]}),o.showAvatar&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(m,{label:(0,l.__)("Avatar Size","wedocs"),widthValue:o.avatarSize,onWidthChange:e=>a({avatarSize:e}),showHeight:!1}),(0,c.jsx)(g,{label:(0,l.__)("Avatar Spacing","wedocs"),paddingValue:o.avatarPadding,onPaddingChange:e=>a({avatarPadding:e}),marginValue:o.avatarMargin,onMarginChange:e=>a({avatarMargin:e}),showGap:!1}),(0,c.jsx)(u,{label:(0,l.__)("Avatar Border","wedocs"),borderStyle:o.avatarBorderStyle,onBorderStyleChange:e=>a({avatarBorderStyle:e}),borderWidth:o.avatarBorderWidth,onBorderWidthChange:e=>a({avatarBorderWidth:e}),borderColor:o.avatarBorderColor,onBorderColorChange:e=>a({avatarBorderColor:e}),borderRadius:o.avatarBorderRadius,onBorderRadiusChange:e=>a({avatarBorderRadius:e})}),(0,c.jsx)(x,{label:(0,l.__)("Avatar Shadow","wedocs"),shadowValue:o.avatarBoxShadow,onShadowChange:e=>a({avatarBoxShadow:e})})]}),(0,c.jsx)(h,{label:(0,l.__)("Name Typography","wedocs"),value:o.nameTypography,onChange:e=>a({nameTypography:e}),colorValue:o.nameColor,onColorChange:e=>a({nameColor:e}),hoverColorValue:o.nameHoverColor,onHoverColorChange:e=>a({nameHoverColor:e})}),(0,c.jsx)(g,{label:(0,l.__)("Name Spacing","wedocs"),paddingValue:o.namePadding,onPaddingChange:e=>a({namePadding:e}),marginValue:o.nameMargin,onMarginChange:e=>a({nameMargin:e}),showGap:!1}),o.showLastUpdated&&(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(h,{label:(0,l.__)("Date Typography","wedocs"),value:o.dateTypography,onChange:e=>a({dateTypography:e}),colorValue:o.dateColor,onColorChange:e=>a({dateColor:e}),showHoverColor:!1}),(0,c.jsx)(g,{label:(0,l.__)("Date Spacing","wedocs"),paddingValue:o.datePadding,onPaddingChange:e=>a({datePadding:e}),marginValue:o.dateMargin,onMarginChange:e=>a({dateMargin:e}),showGap:!1})]})]})]})}),(0,c.jsx)("div",{...T,children:(()=>{if(j)return(0,c.jsxs)(r.Placeholder,{icon:"groups",label:(0,l.__)("Doc Contributors","wedocs"),children:[(0,c.jsx)(r.Spinner,{}),(0,c.jsx)("div",{children:(0,l.__)("Loading contributors...","wedocs")})]});if("manual"===o.contributorDisplayMode&&0===o.selectedContributors.length)return(0,c.jsx)(r.Placeholder,{icon:"groups",label:(0,l.__)("Doc Contributors","wedocs"),instructions:(0,l.__)("Select contributors from the settings panel.","wedocs")});let e=y;e&&0!==e.length||(e=[{id:1,name:"Demo Author",avatar_urls:{48:_}}]);const a={width:o.avatarSize,height:o.avatarSize,borderRadius:"circle"===o.avatarShape?"50%":"rounded"===o.avatarShape?o.avatarBorderRadius:"0",borderStyle:"none"!==o.avatarBorderStyle?o.avatarBorderStyle:void 0,borderColor:"none"!==o.avatarBorderStyle?o.avatarBorderColor:void 0,borderWidth:"none"!==o.avatarBorderStyle?`${o.avatarBorderWidth?.top||"2px"} ${o.avatarBorderWidth?.right||"2px"} ${o.avatarBorderWidth?.bottom||"2px"} ${o.avatarBorderWidth?.left||"2px"}`:void 0,padding:`${o.avatarPadding?.top||"0px"} ${o.avatarPadding?.right||"0px"} ${o.avatarPadding?.bottom||"0px"} ${o.avatarPadding?.left||"0px"}`,margin:`${o.avatarMargin?.top||"0px"} ${o.avatarMargin?.right||"8px"} ${o.avatarMargin?.bottom||"0px"} ${o.avatarMargin?.left||"0px"}`,boxShadow:o.avatarBoxShadow?.enabled?`${o.avatarBoxShadow.horizontal} ${o.avatarBoxShadow.vertical} ${o.avatarBoxShadow.blur} ${o.avatarBoxShadow.spread} ${o.avatarBoxShadow.color}`:void 0},t={color:o.contributorTitleColor,fontSize:o.contributorTitleTypography.fontSize,fontWeight:o.contributorTitleTypography.fontWeight,fontStyle:o.contributorTitleTypography.fontStyle,fontFamily:"default"!==o.contributorTitleTypography.fontFamily?o.contributorTitleTypography.fontFamily:void 0,lineHeight:"normal"!==o.contributorTitleTypography.lineHeight?o.contributorTitleTypography.lineHeight:void 0,letterSpacing:"normal"!==o.contributorTitleTypography.letterSpacing?o.contributorTitleTypography.letterSpacing:void 0,textTransform:"none"!==o.contributorTitleTypography.textTransform?o.contributorTitleTypography.textTransform:void 0,textDecoration:"none"!==o.contributorTitleTypography.textDecoration?o.contributorTitleTypography.textDecoration:void 0,padding:`${o.titlePadding?.top||"0px"} ${o.titlePadding?.right||"0px"} ${o.titlePadding?.bottom||"10px"} ${o.titlePadding?.left||"0px"}`,margin:`${o.titleMargin?.top||"0px"} ${o.titleMargin?.right||"0px"} ${o.titleMargin?.bottom||"0px"} ${o.titleMargin?.left||"0px"}`},n={color:o.nameColor,fontSize:o.nameTypography.fontSize,fontWeight:o.nameTypography.fontWeight,fontStyle:o.nameTypography.fontStyle,fontFamily:"default"!==o.nameTypography.fontFamily?o.nameTypography.fontFamily:void 0,lineHeight:"normal"!==o.nameTypography.lineHeight?o.nameTypography.lineHeight:void 0,letterSpacing:"normal"!==o.nameTypography.letterSpacing?o.nameTypography.letterSpacing:void 0,textTransform:"none"!==o.nameTypography.textTransform?o.nameTypography.textTransform:void 0,textDecoration:"none"!==o.nameTypography.textDecoration?o.nameTypography.textDecoration:void 0,padding:`${o.namePadding?.top||"0px"} ${o.namePadding?.right||"0px"} ${o.namePadding?.bottom||"0px"} ${o.namePadding?.left||"0px"}`,margin:`${o.nameMargin?.top||"0px"} ${o.nameMargin?.right||"0px"} ${o.nameMargin?.bottom||"0px"} ${o.nameMargin?.left||"0px"}`},i={color:o.dateColor,fontSize:o.dateTypography.fontSize,fontWeight:o.dateTypography.fontWeight,fontStyle:o.dateTypography.fontStyle,fontFamily:"default"!==o.dateTypography.fontFamily?o.dateTypography.fontFamily:void 0,lineHeight:"normal"!==o.dateTypography.lineHeight?o.dateTypography.lineHeight:void 0,letterSpacing:"normal"!==o.dateTypography.letterSpacing?o.dateTypography.letterSpacing:void 0,textTransform:"none"!==o.dateTypography.textTransform?o.dateTypography.textTransform:void 0,textDecoration:"none"!==o.dateTypography.textDecoration?o.dateTypography.textDecoration:void 0,padding:`${o.datePadding?.top||"0px"} ${o.datePadding?.right||"0px"} ${o.datePadding?.bottom||"0px"} ${o.datePadding?.left||"0px"}`,margin:`${o.dateMargin?.top||"10px"} ${o.dateMargin?.right||"0px"} ${o.dateMargin?.bottom||"0px"} ${o.dateMargin?.left||"0px"}`};return(0,c.jsxs)("div",{children:[o.showTitle&&(0,c.jsx)("h3",{style:t,children:o.title}),(0,c.jsx)("div",{style:{display:"flex",alignItems:"center",flexWrap:"wrap",gap:o.contributorGap||"10px"},children:o.showAvatar&&e.map(e=>{const t=e.name||e.display_name||"Unknown",l=e.id||e.ID||Math.random();let r=_;if(e.avatar_urls&&(r=e.avatar_urls[48]||e.avatar_urls[96]||e.avatar_urls[24]),!r&&e.email)try{r=`https://www.gravatar.com/avatar/${btoa(e.email.toLowerCase().trim())}?s=48&d=identicon`}catch(e){r=_}return(0,c.jsxs)("div",{style:{display:"flex",alignItems:"center"},children:["user_avatar"===o.avatarType?(0,c.jsx)("img",{src:r,alt:t,style:a}):(0,c.jsx)("div",{style:{...a,backgroundColor:"#0073aa",display:"flex",alignItems:"center",justifyContent:"center"},children:(0,c.jsx)("svg",{width:"16",height:"16",fill:"white",viewBox:"0 0 24 24",children:(0,c.jsx)("path",{d:"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z"})})}),(0,c.jsx)("span",{style:n,children:t})]},l)})}),o.showLastUpdated&&(0,c.jsxs)("div",{style:i,children:[o.datePrefix," ",(new Date).toLocaleDateString("en-US",{year:"numeric",month:"long",day:"numeric"})]})]})})()})]}):(0,c.jsxs)(c.Fragment,{children:[(0,c.jsx)(n.InspectorControls,{children:(0,c.jsx)(r.PanelBody,{title:(0,l.__)("Doc Contributors - PRO Feature","wedocs"),initialOpen:!0,children:(0,c.jsxs)("div",{style:{padding:"20px",textAlign:"center"},children:[(0,c.jsx)("div",{style:{marginBottom:"15px"},children:(0,c.jsx)("svg",{width:"48",height:"48",fill:"#4f47e6",viewBox:"0 0 20 15",children:(0,c.jsx)("path",{d:"M19.213 4.116c.003.054-.001.108-.015.162l-1.234 6.255a.56.56 0 0 1-.541.413l-7.402.036h-.003-7.402c-.257 0-.482-.171-.544-.414L.839 4.295a.53.53 0 0 1-.015-.166C.347 3.983 0 3.548 0 3.036c0-.632.528-1.145 1.178-1.145s1.178.514 1.178 1.145a1.13 1.13 0 0 1-.43.884L3.47 5.434c.39.383.932.602 1.486.602.655 0 1.28-.303 1.673-.81l2.538-3.272c-.213-.207-.345-.494-.345-.809C8.822.514 9.351 0 10 0s1.178.514 1.178 1.145c0 .306-.125.584-.327.79l.002.003 2.52 3.281c.393.512 1.02.818 1.677.818a2.11 2.11 0 0 0 1.481-.597l1.554-1.512c-.268-.21-.44-.531-.44-.892 0-.632.528-1.145 1.177-1.145S20 2.405 20 3.036c0 .498-.329.922-.787 1.079zm-1.369 8.575c0-.301-.251-.545-.561-.545H2.779c-.31 0-.561.244-.561.545V14c0 .301.251.546.561.546h14.505c.31 0 .561-.244.561-.546v-1.309z"})})}),(0,c.jsx)("h3",{style:{margin:"0 0 10px 0",fontSize:"16px",fontWeight:"600"},children:(0,l.__)("This is a PRO Feature","wedocs")}),(0,c.jsx)("p",{style:{margin:"0 0 20px 0",color:"#666",fontSize:"14px"},children:(0,l.__)("The Contributors block requires weDocs Pro to be active.","wedocs")}),(0,c.jsx)("a",{href:"https://wedocs.co/pricing/",target:"_blank",rel:"noopener noreferrer",style:{display:"inline-block",padding:"10px 20px",backgroundColor:"#4f47e6",color:"#fff",textDecoration:"none",borderRadius:"4px",fontWeight:"600",fontSize:"14px"},children:(0,l.__)("Purchase weDocs Pro","wedocs")})]})})}),(0,c.jsx)("div",{...T,children:(0,c.jsx)(r.Placeholder,{icon:(0,c.jsx)("svg",{width:"48",height:"48",fill:"#4f47e6",viewBox:"0 0 20 15",children:(0,c.jsx)("path",{d:"M19.213 4.116c.003.054-.001.108-.015.162l-1.234 6.255a.56.56 0 0 1-.541.413l-7.402.036h-.003-7.402c-.257 0-.482-.171-.544-.414L.839 4.295a.53.53 0 0 1-.015-.166C.347 3.983 0 3.548 0 3.036c0-.632.528-1.145 1.178-1.145s1.178.514 1.178 1.145a1.13 1.13 0 0 1-.43.884L3.47 5.434c.39.383.932.602 1.486.602.655 0 1.28-.303 1.673-.81l2.538-3.272c-.213-.207-.345-.494-.345-.809C8.822.514 9.351 0 10 0s1.178.514 1.178 1.145c0 .306-.125.584-.327.79l.002.003 2.52 3.281c.393.512 1.02.818 1.677.818a2.11 2.11 0 0 0 1.481-.597l1.554-1.512c-.268-.21-.44-.531-.44-.892 0-.632.528-1.145 1.177-1.145S20 2.405 20 3.036c0 .498-.329.922-.787 1.079zm-1.369 8.575c0-.301-.251-.545-.561-.545H2.779c-.31 0-.561.244-.561.545V14c0 .301.251.546.561.546h14.505c.31 0 .561-.244.561-.546v-1.309z"})}),label:(0,l.__)("Doc Contributors - PRO Feature","wedocs"),instructions:(0,l.__)("This block requires weDocs Pro to be active.","wedocs"),children:(0,c.jsx)("a",{href:"https://wedocs.co/pricing/",target:"_blank",rel:"noopener noreferrer",style:{display:"inline-block",padding:"10px 20px",backgroundColor:"#4f47e6",color:"#fff",textDecoration:"none",borderRadius:"4px",fontWeight:"600",fontSize:"14px",marginTop:"10px"},children:(0,l.__)("Purchase weDocs Pro","wedocs")})})})]})}),C=JSON.parse('{"UU":"wedocs/contributors"}');var w=a(5573);const y=(0,c.jsx)(w.SVG,{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24",children:(0,c.jsx)(w.Path,{d:"M11.776 4.454a.25.25 0 01.448 0l2.069 4.192a.25.25 0 00.188.137l4.626.672a.25.25 0 01.139.426l-3.348 3.263a.25.25 0 00-.072.222l.79 4.607a.25.25 0 01-.362.263l-4.138-2.175a.25.25 0 00-.232 0l-4.138 2.175a.25.25 0 01-.363-.263l.79-4.607a.25.25 0 00-.071-.222L4.754 9.881a.25.25 0 01.139-.426l4.626-.672a.25.25 0 00.188-.137l2.069-4.192z"})});(0,t.registerBlockType)(C.UU,{edit:v,save:()=>null,icon:{src:()=>(0,c.jsxs)("span",{style:{position:"relative",display:"inline-block"},children:[(0,c.jsx)(r.Icon,{icon:y}),(0,c.jsx)("span",{style:{position:"absolute",top:"22px",right:"-2px",background:"#4f47e6",color:"white",fontSize:"9px",padding:"2px 3px",borderRadius:"3px",fontWeight:"bold",lineHeight:1},children:"PRO"})]})}})},6427:e=>{e.exports=window.wp.components},7143:e=>{e.exports=window.wp.data},7450:(e,o,a)=>{var t=a(4997),l=a(7723),n=a(5573),r=a(790);const i=(0,r.jsx)(n.SVG,{viewBox:"0 0 24 24",xmlns:"http://www.w3.org/2000/svg",children:(0,r.jsx)(n.Path,{d:"M12 8c-2.2 0-4 1.8-4 4s1.8 4 4 4 4-1.8 4-4-1.8-4-4-4zm0 6.5c-1.4 0-2.5-1.1-2.5-2.5s1.1-2.5 2.5-2.5 2.5 1.1 2.5 2.5-1.1 2.5-2.5 2.5zM12.8 3h-1.5v3h1.5V3zm-1.6 18h1.5v-3h-1.5v3zm6.8-9.8v1.5h3v-1.5h-3zm-12 0H3v1.5h3v-1.5zm9.7 5.6 2.1 2.1 1.1-1.1-2.1-2.1-1.1 1.1zM8.3 7.2 6.2 5.1 5.1 6.2l2.1 2.1 1.1-1.1zM5.1 17.8l1.1 1.1 2.1-2.1-1.1-1.1-2.1 2.1zM18.9 6.2l-1.1-1.1-2.1 2.1 1.1 1.1 2.1-2.1z"})});var s=a(684),d=a(6087),c=a(4715),p=a(6427);const h=({label:e,value:o,unit:a,onValueChange:t,onUnitChange:n})=>(0,r.jsxs)(p.Flex,{children:[(0,r.jsx)(p.FlexBlock,{children:(0,r.jsx)(p.TextControl,{label:e,value:parseInt(o),onChange:e=>t(e)})}),(0,r.jsx)(p.FlexItem,{children:(0,r.jsx)(p.SelectControl,{label:(0,l.__)("Unit","wedocs"),value:a,options:[{label:"px",value:"px"},{label:"%",value:"%"}],onChange:e=>n(e)})})]}),g=({selected:e,options:o,onChange:a})=>(0,r.jsx)(p.BaseControl,{children:(0,r.jsx)("div",{className:"radio-image-control-options",children:o.map(o=>(0,r.jsxs)("div",{className:"radio-image-option",children:[(0,r.jsx)("input",{type:"radio",id:`radio-image-${o.value}`,value:o.value,checked:e===o.value,onChange:e=>a(e.target.value)}),(0,r.jsxs)("label",{htmlFor:`radio-image-${o.value}`,children:[o.icon&&(0,r.jsx)("i",{className:`dashicons ${o.icon}`}),o.img&&(0,r.jsx)("img",{src:o.img,alt:o.label}),o?.svg]})]},o.value))})}),u={hideSearch:{type:"boolean",default:!1},searchWidth:{type:"number",default:50},widthUnit:{type:"string",default:"%"},placeholder:{type:"string",default:(0,l.__)("Search for a top or question","wedocs")},alignment:{type:"string",default:"right"},bgColor:{type:"string",default:"#FFFFFF"},hoverColor:{type:"string",default:"#FFFFFF"},padding:{type:"object",default:{top:14,left:22,right:22,bottom:14}},margin:{type:"object",default:{top:0,left:0,right:0,bottom:0}},borderColor:{type:"string",default:"#cccccc"},borderType:{type:"string",default:"solid"},borderWidth:{type:"number",default:1},borderRadius:{type:"number",default:30},iconColor:{type:"string",default:"#FFFFFF"},iconBgColor:{type:"string",default:"#3b82f6"},iconHoverColor:{type:"string",default:"#2563eb"},svgHoverColor:{type:"string",default:"#FFFFFF"},btnPadding:{type:"object",default:{top:24,left:26,right:26,bottom:24}},btnPosition:{type:"object",default:{top:0,right:0,bottom:10}},btnRadius:{type:"number",default:30}};(0,t.registerBlockType)("wedocs/wedocs-search",{attributes:u,save:({attributes:e})=>{const{margin:o,bgColor:a,padding:t,btnRadius:l,alignment:n,iconColor:i,widthUnit:s,hoverColor:p,borderType:h,hideSearch:g,btnPadding:u,searchWidth:b,btnPosition:x,placeholder:m,borderColor:_,borderWidth:v,iconBgColor:C,borderRadius:w,svgHoverColor:y,iconHoverColor:f}=e;if(g)return;const j={display:"flex",justifyContent:n},S={border:`${v}px ${h} ${_}`,paddingTop:t?.top,paddingLeft:t?.left,paddingRight:t?.right,borderRadius:`${w}px`,paddingBottom:t?.bottom,"--field-color":a,"--field-bg-color":p},B={top:x?.top,left:x?.left,right:x?.right,bottom:x?.bottom,height:"auto",paddingTop:u?.top,paddingLeft:u?.left,borderRadius:l,paddingRight:u?.right,paddingBottom:u?.bottom,"--field-icon-color":i,"--field-btn-bg-color":C,"--field-icon-hover-color":y,"--field-btn-bg-hover-color":f};return(0,r.jsx)(d.Fragment,{children:(0,r.jsx)("form",{method:"get",role:"search",action:weDocsBlockVars?.siteUrl,...c.useBlockProps.save({className:"search-form wedocs-search-form"}),children:(0,r.jsx)("div",{style:j,children:(0,r.jsxs)("div",{className:"wedocs-search-input",style:{width:b+s,marginTop:o?.top,marginLeft:o?.left,marginRight:o?.right,marginBottom:o?.bottom},children:[(0,r.jsx)("input",{name:"s",type:"search",style:S,className:"search-field",placeholder:m}),(0,r.jsx)("input",{type:"hidden",name:"post_type",value:"docs"}),(0,r.jsx)("button",{type:"submit",style:B,className:"search-submit",children:(0,r.jsx)("svg",{width:"15",height:"16",fill:"none",children:(0,r.jsx)("path",{fillRule:"evenodd",d:"M11.856 10.847l2.883 2.883a.89.89 0 0 1 0 1.257c-.173.174-.401.261-.629.261s-.455-.087-.629-.261l-2.883-2.883c-1.144.874-2.532 1.353-3.996 1.353a6.56 6.56 0 0 1-4.671-1.935c-2.576-2.575-2.576-6.765 0-9.341C3.179.934 4.839.247 6.603.247s3.424.687 4.671 1.935a6.56 6.56 0 0 1 1.935 4.67 6.55 6.55 0 0 1-1.353 3.995zM3.189 3.439c-1.882 1.882-1.882 4.945 0 6.827.912.912 2.124 1.414 3.414 1.414s2.502-.502 3.414-1.414 1.414-2.124 1.414-3.413-.502-2.502-1.414-3.413-2.124-1.414-3.414-1.414-2.502.502-3.414 1.414z"})})})]})})})})},edit:({attributes:e,setAttributes:o})=>{const a=(0,c.useBlockProps)(),{margin:t,bgColor:n,padding:u,btnRadius:b,alignment:x,iconColor:m,widthUnit:_,hoverColor:v,borderType:C,hideSearch:w,btnPadding:y,searchWidth:f,btnPosition:j,placeholder:S,borderColor:B,borderWidth:T,iconBgColor:k,borderRadius:P,svgHoverColor:$,iconHoverColor:F}=e;console.log("editor panel:",n);const M=[{value:"left",label:(0,l.__)("Align left","wedocs"),svg:(0,r.jsx)("svg",{width:"24",height:"25",fill:"none",strokeWidth:"2",strokeLinecap:"round",stroke:"left"===x?"#007cba":"#939494",strokeLinejoin:"round",children:(0,r.jsx)("path",{d:"M8 9.462h12m-12 6h6m-10-9v12"})})},{value:"center",label:(0,l.__)("Align center","wedocs"),svg:(0,r.jsxs)("svg",{width:"24",height:"25",fill:"none",strokeWidth:"2",strokeLinecap:"round",stroke:"center"===x?"#007cba":"#939494",strokeLinejoin:"round",children:[(0,r.jsx)("path",{d:"M18 9.462H6m8.99 6h-6"}),(0,r.jsx)("path",{d:"M12 6.462v12"})]})},{value:"right",label:(0,l.__)("Align right","wedocs"),svg:(0,r.jsx)("svg",{width:"24",height:"25",fill:"none",strokeWidth:"2",strokeLinecap:"round",stroke:"right"===x?"#007cba":"#939494",strokeLinejoin:"round",children:(0,r.jsx)("path",{d:"M16 9.462H4m12 6h-6m10-9v12"})})}],[R,D]=(0,d.useState)(!1),[H,W]=(0,d.useState)(!1),[O,N]=(0,d.useState)(!1),z={display:"flex",justifyContent:x},L={border:`${T}px ${C} ${B}`,paddingTop:u?.top,background:R?v:n,paddingLeft:u?.left,paddingRight:u?.right,borderRadius:`${P}px`,paddingBottom:u?.bottom},A={top:j?.top,left:j?.left,right:j?.right,bottom:j?.bottom,height:"auto",background:O?F:k,paddingTop:y?.top,paddingLeft:y?.left,borderRadius:b,paddingRight:y?.right,paddingBottom:y?.bottom},U=[{label:(0,l.__)("Solid","wedocs"),value:"solid"},{label:(0,l.__)("Dotted","wedocs"),value:"dotted"},{label:(0,l.__)("Dashed","wedocs"),value:"dashed"},{label:(0,l.__)("Double","wedocs"),value:"double"},{label:(0,l.__)("Groove","wedocs"),value:"groove"},{label:(0,l.__)("Ridge","wedocs"),value:"ridge"},{label:(0,l.__)("Inset","wedocs"),value:"inset"},{label:(0,l.__)("Outset","wedocs"),value:"outset"},{label:(0,l.__)("None","wedocs"),value:"none"},{label:(0,l.__)("Hidden","wedocs"),value:"hidden"}];return(0,r.jsxs)(d.Fragment,{children:[(0,r.jsxs)(c.InspectorControls,{children:[(0,r.jsx)(p.PanelBody,{children:(0,r.jsx)(p.ToggleControl,{checked:w,className:"wedocs-search-toggle",label:(0,l.__)("Disable Block","wedocs"),onChange:e=>o({hideSearch:e})})}),!w&&(0,r.jsxs)(d.Fragment,{children:[(0,r.jsx)(p.PanelBody,{title:(0,l.__)("Color Settings","wedocs"),icon:i,initialOpen:!1,className:"wedocs-search-color-settings",children:(0,r.jsx)(c.PanelColorSettings,{colors:[{name:"Sweet",color:"#F43F5E"},{name:"Orange",color:"#F97316"},{name:"Yellow",color:"#FACC15"},{name:"Purple",color:"#8B5CF6"},{name:"Light Blue",color:"#3B82F6"},{name:"Light Green",color:"#10B981"}],colorSettings:[{value:n,label:(0,l.__)("Field Background Color","wedocs"),onChange:e=>o({bgColor:e})},{value:v,label:(0,l.__)("Field Hover Color","wedocs"),onChange:e=>o({hoverColor:e})},{value:B,label:(0,l.__)("Border Color","wedocs"),onChange:e=>o({borderColor:e})},{value:m,label:(0,l.__)("Icon Color","wedocs"),onChange:e=>o({iconColor:e})},{value:k,label:(0,l.__)("Button Color","wedocs"),onChange:e=>o({iconBgColor:e})},{value:F,label:(0,l.__)("Button Hover Color","wedocs"),onChange:e=>o({iconHoverColor:e})},{value:$,label:(0,l.__)("Icon Hover Color","wedocs"),onChange:e=>o({svgHoverColor:e})}]})}),(0,r.jsxs)(p.PanelBody,{title:(0,l.__)("Search Bar Settings","wedocs"),icon:s.A,children:[(0,r.jsx)(h,{unit:_,value:f,label:(0,l.__)("Field Width","wedocs"),onUnitChange:e=>o({widthUnit:e}),onValueChange:e=>o({searchWidth:e?parseInt(e):0})}),(0,r.jsx)(p.TextControl,{value:S,label:(0,l.__)("Placeholder","wedocs"),placeholder:(0,l.__)("Search bar placeholder","wedocs"),onChange:e=>o({placeholder:e})}),(0,r.jsx)("p",{style:{fontSize:11},children:(0,l.__)("POSITION","wedocs")}),(0,r.jsx)(g,{selected:x,options:M,onChange:e=>o({alignment:e})}),(0,r.jsx)(p.__experimentalBoxControl,{resetValues:{top:"14px",left:"22px",right:"22px",bottom:"14px"},values:u,label:(0,l.__)("Field Padding","wedocs"),onChange:e=>o({padding:e})}),(0,r.jsx)(p.__experimentalBoxControl,{resetValues:{top:"0px",left:"0px",right:"0px",bottom:"0px"},values:t,label:(0,l.__)("Field Margin","wedocs"),onChange:e=>o({margin:e})}),(0,r.jsx)(p.RangeControl,{min:0,max:10,value:T,label:(0,l.__)("Border Width","wedocs"),onChange:e=>o({borderWidth:e})}),(0,r.jsx)(p.RangeControl,{min:0,max:100,value:P,label:(0,l.__)("Border Radius","wedocs"),onChange:e=>o({borderRadius:e})}),(0,r.jsx)(p.SelectControl,{value:C,options:U,label:(0,l.__)("Border Type","wedocs"),onChange:e=>o({borderType:e})}),(0,r.jsx)(p.__experimentalBoxControl,{resetValues:{top:"24px",left:"26px",right:"26px",bottom:"24px"},values:y,label:(0,l.__)("Button Padding","wedocs"),onChange:e=>o({btnPadding:e})}),(0,r.jsx)(p.__experimentalBoxControl,{resetValues:{top:"0px",right:"0px",bottom:"10px"},values:j,label:(0,l.__)("Button Margin","wedocs"),onChange:e=>o({btnPosition:e})}),(0,r.jsx)(p.RangeControl,{min:0,max:100,value:b,label:(0,l.__)("Button Radius","wedocs"),onChange:e=>o({btnRadius:e})})]})]})]}),(0,r.jsxs)("div",{...a,style:z,children:[(0,r.jsxs)("div",{className:"wedocs-editor-search-input",style:{width:f+_,marginTop:t?.top,marginLeft:t?.left,marginRight:t?.right,marginBottom:t?.bottom},children:[(0,r.jsx)("input",{readOnly:!0,style:L,className:"search-field",placeholder:S,onMouseEnter:()=>D(!0),onMouseLeave:()=>D(!1)}),(0,r.jsx)("input",{type:"hidden",name:"post_type",value:"docs"}),(0,r.jsx)("button",{type:"submit",style:A,className:"search-submit",onMouseEnter:()=>N(!0),onMouseLeave:()=>N(!1),children:(0,r.jsx)("svg",{width:"15",height:"16",fill:"none",onMouseEnter:()=>W(!0),onMouseLeave:()=>W(!1),children:(0,r.jsx)("path",{fill:H?$:m,fillRule:"evenodd",d:"M11.856 10.847l2.883 2.883a.89.89 0 0 1 0 1.257c-.173.174-.401.261-.629.261s-.455-.087-.629-.261l-2.883-2.883c-1.144.874-2.532 1.353-3.996 1.353a6.56 6.56 0 0 1-4.671-1.935c-2.576-2.575-2.576-6.765 0-9.341C3.179.934 4.839.247 6.603.247s3.424.687 4.671 1.935a6.56 6.56 0 0 1 1.935 4.67 6.55 6.55 0 0 1-1.353 3.995zM3.189 3.439c-1.882 1.882-1.882 4.945 0 6.827.912.912 2.124 1.414 3.414 1.414s2.502-.502 3.414-1.414 1.414-2.124 1.414-3.413-.502-2.502-1.414-3.413-2.124-1.414-3.414-1.414-2.502.502-3.414 1.414z"})})})]}),w&&(0,r.jsx)("div",{className:"backdrop"})]})]})},icon:(0,r.jsx)("svg",{width:"20",height:"20",viewBox:"0 0 20 20",fill:"none",children:(0,r.jsx)("path",{fillRule:"evenodd",clipRule:"evenodd",d:"M8.91421 1.5H5.5C4.39543 1.5 3.5 2.39543 3.5 3.5V6.91421V9.02779V15.5C3.5 16.6046 4.39543 17.5 5.5 17.5H7.02779C6.07771 16.4385 5.5 15.0367 5.5 13.5C5.5 10.1863 8.18629 7.5 11.5 7.5C13.0367 7.5 14.4385 8.07771 15.5 9.02779V8.5V6.91421C15.5 6.38378 15.2893 5.87507 14.9142 5.5L11.5 2.08579C11.1249 1.71071 10.6162 1.5 10.0858 1.5H8.91421ZM15.5 13.5C15.5 11.2909 13.7091 9.5 11.5 9.5C9.29086 9.5 7.5 11.2909 7.5 13.5C7.5 15.7091 9.29086 17.5 11.5 17.5C12.2414 17.5 12.9364 17.2977 13.5318 16.946L14.7929 18.2071C15.1834 18.5976 15.8166 18.5976 16.2071 18.2071C16.5976 17.8166 16.5976 17.1834 16.2071 16.7929L14.946 15.5318C15.2977 14.9364 15.5 14.2414 15.5 13.5ZM11.5 11.5C12.6046 11.5 13.5 12.3954 13.5 13.5C13.5 14.0526 13.2772 14.5512 12.9142 14.9142C12.5512 15.2772 12.0526 15.5 11.5 15.5C10.3954 15.5 9.5 14.6046 9.5 13.5C9.5 12.3954 10.3954 11.5 11.5 11.5Z",fill:"#111827"})}),title:(0,l.__)("weDocs - Searchbar","wedocs"),keywords:["Search","weDocs search bar","Bar"],category:"widgets",description:(0,l.__)("Simple search forms for easy user guidance for your documentation","wedocs")}),a(9033),a(6239),a(2317)},7723:e=>{e.exports=window.wp.i18n},9033:(e,o,a)=>{var t=a(4997),l=a(7723),n=a(684),r=a(6087),i=a(4715),s=a(6427),d=a(790);const c=({attributes:e,setAttributes:o})=>{const a=e=>a=>{o({[e]:a})},t=((0,l.__)("Solid","wedocs"),(0,l.__)("Dashed","wedocs"),(0,l.__)("Dotted","wedocs"),(0,l.__)("None","wedocs"),[{name:"Sweet",color:"#F43F5E"},{name:"Orange",color:"#F97316"},{name:"Yellow",color:"#FACC15"},{name:"Purple",color:"#8B5CF6"},{name:"Light Blue",color:"#3B82F6"},{name:"Light Green",color:"#10B981"}]);return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsxs)(s.PanelBody,{title:(0,l.__)("Grid Styles","wedocs"),icon:"admin-appearance",initialOpen:!1,children:[(0,d.jsx)("label",{children:(0,l.__)("Colors","wedocs")}),(0,d.jsx)(i.PanelColorSettings,{colors:t,colorSettings:[{value:e.docTitleColor,label:(0,l.__)("Doc Title Color","wedocs"),onChange:e=>a("docTitleColor")(e)},{value:e.docChildrenActiveColor,label:(0,l.__)("Doc Children Active Color","wedocs"),onChange:e=>a("docChildrenActiveColor")(e)},{value:e.borderColor,label:(0,l.__)("Border Color","wedocs"),onChange:e=>a("borderColor")(e)}]}),(0,d.jsx)(s.__experimentalBoxControl,{label:(0,l.__)("Grid Padding","wedocs"),values:e.gridPadding,onChange:a("gridPadding")}),(0,d.jsx)(s.__experimentalBoxControl,{label:(0,l.__)("Grid Margin","wedocs"),values:e.gridMargin,onChange:a("gridMargin")}),(0,d.jsx)(s.SelectControl,{label:(0,l.__)("Border Type","wedocs"),value:e.borderType,options:[{label:(0,l.__)("Solid","wedocs"),value:"solid"},{label:(0,l.__)("Dashed","wedocs"),value:"dashed"},{label:(0,l.__)("Dotted","wedocs"),value:"dotted"},{label:(0,l.__)("None","wedocs"),value:"none"}],onChange:e=>o({borderType:e})}),(0,d.jsx)(s.SelectControl,{label:(0,l.__)("Border Width","wedocs"),value:e.borderWidth,options:[{label:"0px",value:"0px"},{label:"1px",value:"1px"},{label:"2px",value:"2px"},{label:"3px",value:"3px"},{label:"4px",value:"4px"},{label:"5px",value:"5px"}],onChange:e=>o({borderWidth:e})}),(0,d.jsx)(s.SelectControl,{label:(0,l.__)("Border Radius","wedocs"),value:e.borderRadius,options:[{label:"0px",value:"0px"},{label:"4px",value:"4px"},{label:"8px",value:"8px"},{label:"12px",value:"12px"},{label:"16px",value:"16px"},{label:"20px",value:"20px"}],onChange:e=>o({borderRadius:e})})]}),(0,d.jsxs)(s.PanelBody,{title:(0,l.__)("Button Styles","wedocs"),icon:"admin-appearance",initialOpen:!1,children:[(0,d.jsx)("label",{children:(0,l.__)("Button Colors","wedocs")}),(0,d.jsx)(i.PanelColorSettings,{colors:t,colorSettings:[{value:e.buttonColor,label:(0,l.__)("Button Color","wedocs"),onChange:e=>a("buttonColor")(e)},{value:e.buttonHoverColor,label:(0,l.__)("Button Hover Color","wedocs"),onChange:e=>a("buttonHoverColor")(e)},{value:e.buttonTextColor,label:(0,l.__)("Button Text Color","wedocs"),onChange:e=>a("buttonTextColor")(e)},{value:e.buttonHoverTextColor,label:(0,l.__)("Button Hover Text Color","wedocs"),onChange:e=>a("buttonHoverTextColor")(e)}]}),(0,d.jsx)(s.__experimentalBoxControl,{label:(0,l.__)("Button Padding","wedocs"),values:e.buttonPadding,onChange:a("buttonPadding")}),(0,d.jsx)(s.__experimentalBoxControl,{label:(0,l.__)("Button Margin","wedocs"),values:e.buttonMargin,onChange:a("buttonMargin")}),(0,d.jsx)(s.SelectControl,{label:(0,l.__)("Button Border Radius","wedocs"),value:e.buttonBorderRadius,options:[{label:"0px",value:"0px"},{label:"4px",value:"4px"},{label:"8px",value:"8px"},{label:"12px",value:"12px"},{label:"16px",value:"16px"},{label:"20px",value:"20px"}],onChange:e=>o({buttonBorderRadius:e})}),(0,d.jsxs)("div",{className:"wedocs-color-control",children:[(0,d.jsx)("label",{children:(0,l.__)("Button Text","wedocs")}),(0,d.jsx)(s.TextControl,{value:e.buttonText,onChange:a("buttonText")})]})]})]})},p=JSON.parse('{"UU":"wedocs/wedocs-docs-grid"}');(0,t.registerBlockType)(p.UU,{edit:({attributes:e,setAttributes:o})=>{const a=(0,i.useBlockProps)(),{useSelect:t}=wp.data,[p,h]=(0,r.useState)(1),[g,u]=(0,r.useState)(!1),{hideDocGrid:b,docStyle:x,docsPerPage:m,excludeDocs:_,order:v,orderBy:C,sectionsPerDoc:w,articlesPerSection:y,showDocArticle:f,keepArticlesCollapsed:j,showViewDetails:S,gridPadding:B,gridMargin:T,docTitleColor:k,docChildrenActiveColor:P,borderType:$,borderRadius:F,borderWidth:M,borderColor:R,buttonBorderRadius:D,buttonPadding:H,buttonMargin:W,buttonColor:O,buttonHoverColor:N,buttonTextColor:z,buttonText:L,buttonHoverTextColor:A}=e,U=(e,o)=>e.sections?(0,d.jsxs)("div",{className:"wedocs-docs-grid__sections "+(j?"is-collapsed":""),children:[e.sections.map(e=>(0,d.jsxs)("div",{className:"wedocs-docs-grid__section",children:[(0,d.jsxs)("h4",{className:"wedocs-docs-grid__section-title",style:{...o.title,display:"flex",justifyContent:"space-between",alignItems:"center"},children:[(0,d.jsx)("span",{children:e.title.rendered}),f&&e.articles&&e.articles.length>0&&(0,d.jsx)("svg",{fill:"none",viewBox:"0 0 24 24",width:"16",strokeWidth:"2",stroke:"#acb8c4",className:j?"":"active",children:(0,d.jsx)("path",{strokeLinecap:"round",strokeLinejoin:"round",d:"M19.5 8.25l-7.5 7.5-7.5-7.5"})})]}),f&&!j&&e.articles&&(0,d.jsx)("ul",{className:"wedocs-docs-grid__articles",children:e.articles.map(e=>(0,d.jsx)("li",{className:"wedocs-docs-grid__article",style:o.children,children:e.title.rendered},e.id))})]},e.id)),0===e.sections.length&&(0,d.jsxs)("span",{className:"inside",children:[(0,d.jsx)("svg",{fill:"none",viewBox:"0 0 24 24","stroke-width":"1.5",stroke:"currentColor",children:(0,d.jsx)("path",{"stroke-linecap":"round","stroke-linejoin":"round",d:"M11.25 11.25l.041-.02a.75.75 0 011.063.852l-.708 2.836a.75.75 0 001.063.853l.041-.021M21 12a9 9 0 11-18 0 9 9 0 0118 0zm-9-3.75h.008v.008H12V8.25z"})}),(0,l.__)("This document has no sections yet. Check back later or wait for the author to add content.","wedocs")]})]}):null,V=[{label:"All",value:"all"},...Array.from({length:10},(e,o)=>({label:String(o+1),value:String(o+1)}))],I=[{label:(0,l.__)("weDocs Order","wedocs"),value:"menu_order"},{label:(0,l.__)("ID","wedocs"),value:"id"},{label:(0,l.__)("Name","wedocs"),value:"title"}],G=[{label:(0,l.__)("Ascending","wedocs"),value:"asc"},{label:(0,l.__)("Descending","wedocs"),value:"desc"}],E=[{label:"All",value:"all"},...Array.from({length:10},(e,o)=>({label:String(o+1),value:String(o+1)}))],{pages:q,sections:J,articles:Y}=t(e=>{const{getEntityRecords:o}=e("core"),a=o("postType","docs",{status:"publish",per_page:-1,parent:0,orderby:C,order:v}),t=a?o("postType","docs",{status:"publish",parent_in:a.map(e=>e.id),per_page:-1}):null,l=t?o("postType","docs",{status:"publish",parent_in:t.map(e=>e.id),per_page:-1}):null;return{pages:a,sections:t,articles:l}},[C,v]),Z=(e=>{if("all"===m)return e;const o=parseInt(m),a=(p-1)*o,t=a+o;return e.slice(a,t)})((()=>{if(!q||!J||!Y)return[];let e=[...q];return _&&_.length>0&&(e=e.filter(e=>!_.includes(e.id.toString()))),e=e.map(e=>{let o=J.filter(o=>o.parent===e.id);"all"!==w&&(o=o.slice(0,parseInt(w))),o=o.map(e=>{let o=Y.filter(o=>o.parent===e.id);return"all"!==y&&(o=o.slice(0,parseInt(y))),{...e,articles:o}});const a=o.reduce((e,o)=>e+o.articles.length,0);return{...e,sections:o,articleCount:a}}),e})()),K=q?q.reduce((e,o)=>(e[o.id]=o.title.rendered,e),{}):{},X=(q&&q.map(e=>({value:e.id.toString(),label:e.title.rendered})),e=>a=>{o({[e]:a})}),Q=_?_.map(e=>K[e]||e):[];return(0,d.jsxs)(r.Fragment,{children:[(0,d.jsx)(i.InspectorControls,{children:(0,d.jsxs)(s.PanelBody,{title:(0,l.__)("Doc Grid Settings","wedocs"),icon:n.A,initialOpen:!1,children:[(0,d.jsx)(s.SelectControl,{value:x,options:[{label:"1x1",value:"1x1"},{label:"1x2",value:"1x2"}],label:(0,l.__)("DOCS GRID COLUMN STYLE","wedocs"),onChange:X("docStyle")}),(0,d.jsx)(s.SelectControl,{value:m,options:V,label:(0,l.__)("Docs per page","wedocs"),onChange:X("docsPerPage")}),(0,d.jsx)(s.FormTokenField,{value:Q,suggestions:Object.values(K),label:(0,l.__)("Exclude Docs","wedocs"),onChange:e=>{const a=e.map(e=>{const o=Object.entries(K).find(([o,a])=>a===e);return o?o[0]:e});o({excludeDocs:a})}}),(0,d.jsx)(s.SelectControl,{value:v,options:G,label:(0,l.__)("Order","wedocs"),onChange:X("order")}),(0,d.jsx)(s.SelectControl,{value:C,options:I,label:(0,l.__)("Order by","wedocs"),onChange:X("orderBy")}),(0,d.jsx)(s.SelectControl,{value:w,options:E,label:(0,l.__)("Sections per doc","wedocs"),onChange:X("sectionsPerDoc")}),(0,d.jsx)(s.SelectControl,{value:y,options:E,label:(0,l.__)("Articles per section","wedocs"),onChange:X("articlesPerSection")}),(0,d.jsx)(s.PanelRow,{children:(0,d.jsx)(s.ToggleControl,{checked:f,label:(0,l.__)("Show Doc Article","wedocs"),onChange:X("showDocArticle")})}),(0,d.jsx)(s.PanelRow,{children:(0,d.jsx)(s.ToggleControl,{checked:j,label:(0,l.__)("Keep Article Collapsed","wedocs"),onChange:X("keepArticlesCollapsed")})}),(0,d.jsx)(s.PanelRow,{children:(0,d.jsx)(s.ToggleControl,{checked:S,label:(0,l.__)("Show View Details Button","wedocs"),onChange:X("showViewDetails")})})]})}),(0,d.jsx)(i.InspectorControls,{children:(0,d.jsx)(c,{attributes:e,setAttributes:o})}),(0,d.jsx)("div",{...a,children:b?(0,d.jsx)("div",{className:"backdrop"}):(0,d.jsx)("div",{className:"wedocs-block-wrapper",children:(0,d.jsx)("div",{className:`wedocs-docs-grid wedocs-docs-grid--${x}`,children:g?(0,d.jsx)(Spinner,{}):Z.map(e=>((e,o)=>(0,d.jsxs)("div",{className:"wedocs-docs-grid__item",style:o.item,children:[(0,d.jsx)("h3",{className:"wedocs-docs-grid__title",style:o.title,children:e.title.rendered}),U(e,o),S&&(0,d.jsx)("div",{className:"wedocs-docs-grid__details",children:(0,d.jsx)("span",{className:"wedocs-docs-grid__details-link",style:o.button,children:o.button.text})})]},e.id))(e,(()=>{const e=B?`${B.top} ${B.right} ${B.bottom} ${B.left}`:"",o=T?`${T.top} ${T.right} ${T.bottom} ${T.left}`:"",a=H?`${H.top} ${H.right} ${H.bottom} ${H.left}`:"",t=D||"8px",n=W?`${W.top} ${W.right} ${W.bottom} ${W.left}`:"";return{item:{padding:e,margin:o,borderStyle:$||"solid",borderWidth:M||"1px",borderColor:R||"rgba(0, 0, 0, 0.1)",borderRadius:F||"8px",backgroundColor:"#fff"},title:{color:k||"#1e1e1e"},children:{color:P||"#0073aa"},button:{padding:a,margin:n,backgroundColor:O||"#0073aa",color:z||"#ffffff",text:L||(0,l.__)("View Details","wedocs"),borderRadius:t||"8px","--hover-bg":N||"#005177","--hover-color":A||"#ffffff"}}})()))})})})]})},save:()=>null})}},a={};function t(e){var l=a[e];if(void 0!==l)return l.exports;var n=a[e]={exports:{}};return o[e](n,n.exports,t),n.exports}t.m=o,e=[],t.O=(o,a,l,n)=>{if(!a){var r=1/0;for(c=0;c<e.length;c++){for(var[a,l,n]=e[c],i=!0,s=0;s<a.length;s++)(!1&n||r>=n)&&Object.keys(t.O).every(e=>t.O[e](a[s]))?a.splice(s--,1):(i=!1,n<r&&(r=n));if(i){e.splice(c--,1);var d=l();void 0!==d&&(o=d)}}return o}n=n||0;for(var c=e.length;c>0&&e[c-1][2]>n;c--)e[c]=e[c-1];e[c]=[a,l,n]},t.n=e=>{var o=e&&e.__esModule?()=>e.default:()=>e;return t.d(o,{a:o}),o},t.d=(e,o)=>{for(var a in o)t.o(o,a)&&!t.o(e,a)&&Object.defineProperty(e,a,{enumerable:!0,get:o[a]})},t.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),t.o=(e,o)=>Object.prototype.hasOwnProperty.call(e,o),(()=>{var e;t.g.importScripts&&(e=t.g.location+"");var o=t.g.document;if(!e&&o&&(o.currentScript&&"SCRIPT"===o.currentScript.tagName.toUpperCase()&&(e=o.currentScript.src),!e)){var a=o.getElementsByTagName("script");if(a.length)for(var l=a.length-1;l>-1&&(!e||!/^http(s?):/.test(e));)e=a[l--].src}if(!e)throw new Error("Automatic publicPath is not supported in this browser");e=e.replace(/^blob:/,"").replace(/#.*$/,"").replace(/\?.*$/,"").replace(/\/[^\/]+$/,"/"),t.p=e})(),(()=>{var e={4:0,204:0,366:0,687:0,484:0,631:0,380:0,337:0};t.O.j=o=>0===e[o];var o=(o,a)=>{var l,n,[r,i,s]=a,d=0;if(r.some(o=>0!==e[o])){for(l in i)t.o(i,l)&&(t.m[l]=i[l]);if(s)var c=s(t)}for(o&&o(a);d<r.length;d++)n=r[d],t.o(e,n)&&e[n]&&e[n][0](),e[n]=0;return t.O(c)},a=globalThis.webpackChunkweDocs=globalThis.webpackChunkweDocs||[];a.forEach(o.bind(null,0)),a.push=o.bind(null,a.push.bind(a))})();var l=t.O(void 0,[484,631,380,337],()=>t(7450));l=t.O(l)})(); No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

TOC link color custom property likely misbound.

The bundle sets {"--list-item-sytle": containerBackgroundColor}. That appears intended for listColor. Please adjust in the source (e.g., src/blocks/TableOfContents/edit.js) and fix the property name typo across CSS/JS.


I need to verify the source code to confirm the issue. Let me search for the TableOfContents block implementation.

[/run_scripts]

[/run_scripts]

[/run_scripts]


🏁 Script executed:

#!/bin/bash
# Find TableOfContents block source files
fd -type f -name "*.js" -path "*TableOfContents*" | head -20
fd -type f -name "*.jsx" -path "*table-of-contents*" -o -path "*toc*" | grep -v node_modules | head -20

Length of output: 341


🏁 Script executed:

#!/bin/bash
# Search for the specific CSS custom property in source files
rg -n "list-item" --type=js --type=jsx -B2 -A2 | head -50
rg -n "containerBackgroundColor" --type=js --type=jsx -B3 -A3 | grep -i "style\|toc\|list" | head -50

Length of output: 55


🏁 Script executed:

#!/bin/bash
# Look for TOC block edit file and check the style object
find . -type f \( -name "*edit.js" -o -name "*edit.jsx" \) | xargs grep -l "toc\|table-of-contents" -i 2>/dev/null

Length of output: 36


Now let me examine the source file to verify the CSS custom property binding:

[/run_scripts]

[/run_scripts]


🏁 Script executed:

#!/bin/bash
# View the TableOfContents edit.js file
cat ./src/blocks/TableOfContents/edit.js

Length of output: 6113


🏁 Script executed:

#!/bin/bash
# Search for the style object and CSS custom properties in edit.js
grep -n "\-\-list\|containerBackgroundColor\|listColor" ./src/blocks/TableOfContents/edit.js -A2 -B2

Length of output: 695


Fix CSS custom property binding and typo in TableOfContents block.

Line 154 in src/blocks/TableOfContents/edit.js contains two errors:

  • Property name typo: --list-item-sytle should be --list-item-style
  • Wrong variable: should bind listColor (used for list text, line 184) instead of containerBackgroundColor (container background)

Change:

"--list-item-sytle": containerBackgroundColor,

to:

"--list-item-style": listColor,
🧰 Tools
🪛 Biome (2.1.2)

[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: Shouldn't redeclare 'a'. Consider to delete it or rename it.

'a' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: Shouldn't redeclare 'l'. Consider to delete it or rename it.

'l' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: Shouldn't redeclare 'n'. Consider to delete it or rename it.

'n' is defined here:

(lint/suspicious/noRedeclare)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)


[error] 1-1: This variable is used before its declaration.

The variable is declared here:

(lint/correctness/noInvalidUseBeforeDeclaration)

🤖 Prompt for AI Agents
In assets/build/block.js around lines 1 to 1, the inline style object for the
TableOfContents block uses a misspelled CSS custom property and binds the wrong
variable; change the entry that currently sets "--list-item-sytle" to instead
set "--list-item-style" and bind it to the list color variable used elsewhere
(replace the container background variable with the listColor variable).

Comment on lines +266 to +292
"borderAndShadowControls": {
"type": "object",
"default": {
"desktop": {
"borderStyle": "solid",
"borderWidth": {
"top": "1px",
"right": "1px",
"bottom": "1px",
"left": "1px"
},
"borderColor": "#dddddd",
"borderRadius": {
"topLeft": "4px",
"topRight": "4px",
"bottomLeft": "4px",
"bottomRight": "4px"
},
"boxShadow": {
"enabled": false,
"horizontal": "0px",
"vertical": "2px",
"blur": "4px",
"spread": "0px",
"color": "rgba(0,0,0,0.1)"
}
},
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Box shadow schema doesn’t match renderer expectations

Defaults use "horizontal"/"vertical", but the renderer in AdvanceContributors expects "x"/"y", so shadows will never render.

Either:

  • Change defaults to x/y, or
  • Update the renderer to read "horizontal"/"vertical".
    If you keep schema as-is, align the PHP at Box Shadow handling. See related comment in render.php.

Comment on lines +49 to +57
case 'main_author':
$author_id = get_post_field('post_author', $post->ID);
if ($author_id) {
$author_user = get_userdata($author_id);
if ($author_user) {
$contributors[] = $author_user;
}
}
break;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

$post may be null; unsafe property access

Accessing $post->ID without verifying $post will fatal on non-singular contexts or previews.

Guard before use:

-        case 'main_author':
-            $author_id = get_post_field('post_author', $post->ID);
+        case 'main_author':
+            if ( ! $post ) { break; }
+            $author_id = get_post_field('post_author', $post->ID);

Repeat this pattern wherever $post->ID is used.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case 'main_author':
$author_id = get_post_field('post_author', $post->ID);
if ($author_id) {
$author_user = get_userdata($author_id);
if ($author_user) {
$contributors[] = $author_user;
}
}
break;
case 'main_author':
if ( ! $post ) { break; }
$author_id = get_post_field('post_author', $post->ID);
if ($author_id) {
$author_user = get_userdata($author_id);
if ($author_user) {
$contributors[] = $author_user;
}
}
break;
🤖 Prompt for AI Agents
In assets/build/blocks/AdvanceContributors/render.php around lines 49 to 57, the
code accesses $post->ID without ensuring $post is non-null which will fatal in
non-singular contexts; update the case 'main_author' to first check that $post
is an object (e.g. if (!$post || !isset($post->ID)) return/continue or wrap the
block in if ($post && isset($post->ID)) { ... }), then retrieve post_author and
proceed as before; apply the same null-guard pattern to every other location in
this file that accesses $post->ID.

Comment on lines +229 to +242
// Box Shadow
if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['x'])) {
$shadow = $controls['boxShadow'];
$shadow_value = '';
if (isset($shadow['inset']) && $shadow['inset']) {
$shadow_value .= 'inset ';
}
$shadow_value .= esc_attr($shadow['x']) . ' ';
$shadow_value .= esc_attr($shadow['y']) . ' ';
$shadow_value .= esc_attr($shadow['blur']) . ' ';
$shadow_value .= esc_attr($shadow['spread']) . ' ';
$shadow_value .= esc_attr($shadow['color']);
$rules[] = 'box-shadow: ' . $shadow_value;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Box shadow keys mismatch (“x/y” vs “horizontal/vertical”)

This check requires ['x'] but block attributes provide ['horizontal'] and ['vertical']; shadow never applies.

Update to:

-        if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['x'])) {
+        if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['horizontal'])) {
             $shadow = $controls['boxShadow'];
             $shadow_value = '';
             if (isset($shadow['inset']) && $shadow['inset']) {
                 $shadow_value .= 'inset ';
             }
-            $shadow_value .= esc_attr($shadow['x']) . ' ';
-            $shadow_value .= esc_attr($shadow['y']) . ' ';
+            $shadow_value .= esc_attr($shadow['horizontal']) . ' ';
+            $shadow_value .= esc_attr($shadow['vertical']) . ' ';
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Box Shadow
if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['x'])) {
$shadow = $controls['boxShadow'];
$shadow_value = '';
if (isset($shadow['inset']) && $shadow['inset']) {
$shadow_value .= 'inset ';
}
$shadow_value .= esc_attr($shadow['x']) . ' ';
$shadow_value .= esc_attr($shadow['y']) . ' ';
$shadow_value .= esc_attr($shadow['blur']) . ' ';
$shadow_value .= esc_attr($shadow['spread']) . ' ';
$shadow_value .= esc_attr($shadow['color']);
$rules[] = 'box-shadow: ' . $shadow_value;
}
// Box Shadow
if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['horizontal'])) {
$shadow = $controls['boxShadow'];
$shadow_value = '';
if (isset($shadow['inset']) && $shadow['inset']) {
$shadow_value .= 'inset ';
}
$shadow_value .= esc_attr($shadow['horizontal']) . ' ';
$shadow_value .= esc_attr($shadow['vertical']) . ' ';
$shadow_value .= esc_attr($shadow['blur']) . ' ';
$shadow_value .= esc_attr($shadow['spread']) . ' ';
$shadow_value .= esc_attr($shadow['color']);
$rules[] = 'box-shadow: ' . $shadow_value;
}
🤖 Prompt for AI Agents
In assets/build/blocks/AdvanceContributors/render.php around lines 229 to 242,
the box-shadow branch checks for shadow['x'] and shadow['y'] but the block
attributes provide horizontal/vertical keys, so the shadow never applies; update
the guard to check for horizontal/vertical (with fallbacks to x/y for backward
compatibility), read horizontal and vertical into local variables, then build
the shadow string using those values (preserving inset, blur, spread, color and
esc_attr usage) and only add the rule if horizontal/vertical (or their
fallbacks) are present.

Comment on lines +333 to +345
// Handle display controls for hiding on devices
$display_classes = [];
if (isset($display_controls['desktop']) && $display_controls['desktop']) {
$display_classes[] = 'wedocs-hide-desktop';
}
if (isset($display_controls['tablet']) && $display_controls['tablet']) {
$display_classes[] = 'wedocs-hide-tablet';
}
if (isset($display_controls['mobile']) && $display_controls['mobile']) {
$display_classes[] = 'wedocs-hide-mobile';
}
$css_classes = array_merge($css_classes, $display_classes);

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Hide-class logic inverted; always hides on all devices

You append wedocs-hide-{device} when the device key exists (it always does), so the block is hidden across breakpoints.

Only add hide-class when display is explicitly 'none':

-    if (isset($display_controls['desktop']) && $display_controls['desktop']) {
+    if (isset($display_controls['desktop']['display']) && $display_controls['desktop']['display'] === 'none') {
         $display_classes[] = 'wedocs-hide-desktop';
     }
-    if (isset($display_controls['tablet']) && $display_controls['tablet']) {
+    if (isset($display_controls['tablet']['display']) && $display_controls['tablet']['display'] === 'none') {
         $display_classes[] = 'wedocs-hide-tablet';
     }
-    if (isset($display_controls['mobile']) && $display_controls['mobile']) {
+    if (isset($display_controls['mobile']['display']) && $display_controls['mobile']['display'] === 'none') {
         $display_classes[] = 'wedocs-hide-mobile';
     }
🤖 Prompt for AI Agents
In assets/build/blocks/AdvanceContributors/render.php around lines 333 to 345,
the current logic adds wedocs-hide-{device} whenever the device key exists
(which is always true), causing the block to be hidden on all devices; change
the checks so you only append the hide class when the display control for that
device is explicitly 'none' (e.g. isset($display_controls['desktop']) &&
$display_controls['desktop'] === 'none'), repeat for tablet and mobile, then
merge those classes into $css_classes as before.

Comment on lines +53 to +54
<Text>{__('Color', 'block-responsive')}</Text>
</HStack>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Fix text domain: use 'wedocs' instead of 'block-responsive'.

Several strings use 'block-responsive', which will break translations in this plugin. Replace with 'wedocs' throughout this component.

Also applies to: 108-110, 122-139, 157-161, 168-177, 229-230, 242-245, 257-260, 279-281, 322-327

Comment on lines +322 to +347
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
marginTop: '16px',
}}
onClick={() => {
setAttributes({
colorsControls: {
...colorsControls,
[device]: {
...currentColors,
textColor: undefined,
backgroundColor: undefined,
linkColor: undefined,
linkHoverColor: undefined,
},
},
});
}}
/>
</>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Use children for Button label (avoid Button.text for compatibility).

Some versions of @wordpress/components don’t support the “text” prop on Button. Safer to pass children.

- <Button
+ <Button
     __next40pxDefaultSize
     variant="secondary"
     isDestructive
-    text={__('Reset All', 'block-responsive')}
     style={{
       width: '100%',
       justifyContent: 'center',
       marginTop: '16px',
     }}
     onClick={() => {
       setAttributes({
         colorsControls: {
           ...colorsControls,
           [device]: {
             ...currentColors,
             textColor: undefined,
             backgroundColor: undefined,
             linkColor: undefined,
             linkHoverColor: undefined,
           },
         },
       });
     }}
   />
+ >
+   { __('Reset All', 'wedocs') }
+ </Button>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
text={__('Reset All', 'block-responsive')}
style={{
width: '100%',
justifyContent: 'center',
marginTop: '16px',
}}
onClick={() => {
setAttributes({
colorsControls: {
...colorsControls,
[device]: {
...currentColors,
textColor: undefined,
backgroundColor: undefined,
linkColor: undefined,
linkHoverColor: undefined,
},
},
});
}}
/>
</>
<Button
__next40pxDefaultSize
variant="secondary"
isDestructive
style={{
width: '100%',
justifyContent: 'center',
marginTop: '16px',
}}
onClick={() => {
setAttributes({
colorsControls: {
...colorsControls,
[device]: {
...currentColors,
textColor: undefined,
backgroundColor: undefined,
linkColor: undefined,
linkHoverColor: undefined,
},
},
});
}}
>
{__('Reset All', 'block-responsive')}
</Button>
🤖 Prompt for AI Agents
In src/blocks/TableOfContents/ColorsControls.js around lines 322 to 347, the
Button currently uses the text prop which some @wordpress/components versions
don't support; replace the text prop with a child node: remove text={__('Reset
All', 'block-responsive')} and instead place the __('Reset All',
'block-responsive') string as the Button's child content (keeping all other
props and the onClick handler unchanged) so the label is passed via children for
maximum compatibility.

Comment on lines +7 to +25
const ListItems = ({ attributes, setAttributes }) => {
return (
<PanelBody title={__('List Items', 'dynamic-table-of-contents-block-wp')} initialOpen={false}>
<h4>{__('TOC Container', 'dynamic-table-of-contents-block-wp')}</h4>
<div style={{ marginBottom: '20px' }}>
<label>{__('Background Color', 'dynamic-table-of-contents-block-wp')}</label>
<ColorPicker
color={containerBackgroundColor}
onChange={(value) => setAttributes({ containerBackgroundColor: value })}
/>
</div>
{/* <ColorsControls
attributes={attributes}
setAttributes={setAttributes}
device='desktop'
/> */}
</PanelBody>
);
};
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Fix undefined variable reference.

The component references containerBackgroundColor on line 14 without defining it. This will cause a ReferenceError at runtime. The variable should be destructured from attributes or accessed via attributes.containerBackgroundColor.

Apply this diff to fix the issue:

 const ListItems = ({ attributes, setAttributes }) => {
+    const { containerBackgroundColor } = attributes;
+    
     return (
         <PanelBody title={__('List Items', 'dynamic-table-of-contents-block-wp')} initialOpen={false}>

Alternatively, access it directly:

             <div style={{ marginBottom: '20px' }}>
                 <label>{__('Background Color', 'dynamic-table-of-contents-block-wp')}</label>
                 <ColorPicker
-                    color={containerBackgroundColor}
+                    color={attributes.containerBackgroundColor}
                     onChange={(value) => setAttributes({ containerBackgroundColor: value })}
                 />
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const ListItems = ({ attributes, setAttributes }) => {
return (
<PanelBody title={__('List Items', 'dynamic-table-of-contents-block-wp')} initialOpen={false}>
<h4>{__('TOC Container', 'dynamic-table-of-contents-block-wp')}</h4>
<div style={{ marginBottom: '20px' }}>
<label>{__('Background Color', 'dynamic-table-of-contents-block-wp')}</label>
<ColorPicker
color={containerBackgroundColor}
onChange={(value) => setAttributes({ containerBackgroundColor: value })}
/>
</div>
{/* <ColorsControls
attributes={attributes}
setAttributes={setAttributes}
device='desktop'
/> */}
</PanelBody>
);
};
const ListItems = ({ attributes, setAttributes }) => {
const { containerBackgroundColor } = attributes;
return (
<PanelBody title={__('List Items', 'dynamic-table-of-contents-block-wp')} initialOpen={false}>
<h4>{__('TOC Container', 'dynamic-table-of-contents-block-wp')}</h4>
<div style={{ marginBottom: '20px' }}>
<label>{__('Background Color', 'dynamic-table-of-contents-block-wp')}</label>
<ColorPicker
color={containerBackgroundColor}
onChange={(value) => setAttributes({ containerBackgroundColor: value })}
/>
</div>
{/* <ColorsControls
attributes={attributes}
setAttributes={setAttributes}
device='desktop'
/> */}
</PanelBody>
);
};
Suggested change
const ListItems = ({ attributes, setAttributes }) => {
return (
<PanelBody title={__('List Items', 'dynamic-table-of-contents-block-wp')} initialOpen={false}>
<h4>{__('TOC Container', 'dynamic-table-of-contents-block-wp')}</h4>
<div style={{ marginBottom: '20px' }}>
<label>{__('Background Color', 'dynamic-table-of-contents-block-wp')}</label>
<ColorPicker
color={containerBackgroundColor}
onChange={(value) => setAttributes({ containerBackgroundColor: value })}
/>
</div>
{/* <ColorsControls
attributes={attributes}
setAttributes={setAttributes}
device='desktop'
/> */}
</PanelBody>
);
};
const ListItems = ({ attributes, setAttributes }) => {
return (
<PanelBody title={__('List Items', 'dynamic-table-of-contents-block-wp')} initialOpen={false}>
<h4>{__('TOC Container', 'dynamic-table-of-contents-block-wp')}</h4>
<div style={{ marginBottom: '20px' }}>
<label>{__('Background Color', 'dynamic-table-of-contents-block-wp')}</label>
<ColorPicker
color={attributes.containerBackgroundColor}
onChange={(value) => setAttributes({ containerBackgroundColor: value })}
/>
</div>
{/* <ColorsControls
attributes={attributes}
setAttributes={setAttributes}
device='desktop'
/> */}
</PanelBody>
);
};
🤖 Prompt for AI Agents
In src/blocks/TableOfContents/controls/ListItems.js around lines 7 to 25, the
component uses containerBackgroundColor on line 14 but never defines or
destructures it, causing a ReferenceError; fix by extracting
containerBackgroundColor from props (e.g., const { containerBackgroundColor } =
attributes) at the top of the component or replace the reference with
attributes.containerBackgroundColor, and ensure the ColorPicker onChange
continues to call setAttributes({ containerBackgroundColor: value }) so the
attribute is updated correctly.

Comment on lines +1 to +3



No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Empty file with meaningless whitespace; implement like AdvanceContributors or remove entirely.

This file contains only whitespace but no actual code. For server-rendered blocks, you should either:

  1. Implement it like src/blocks/AdvanceContributors/save.js (returning null with proper imports)
  2. Remove the file entirely if not needed

The current whitespace-only content serves no purpose and creates inconsistency.

Apply this diff to implement the proper pattern:

-
-  
-	
+import { useBlockProps } from '@wordpress/block-editor';
+
+const Save = () => {
+	const blockProps = useBlockProps.save();
+
+	// Since this is a dynamic block that uses PHP rendering,
+	// we return null to let the server-side render function handle the output
+	return null;
+};
+
+export default Save;
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
import { useBlockProps } from '@wordpress/block-editor';
const Save = () => {
const blockProps = useBlockProps.save();
// Since this is a dynamic block that uses PHP rendering,
// we return null to let the server-side render function handle the output
return null;
};
export default Save;
🤖 Prompt for AI Agents
In src/blocks/TableOfContents/save.js lines 1-3: the file currently contains
only whitespace; either remove the file or implement the server-rendered block
pattern used by src/blocks/AdvanceContributors/save.js — create a save.js that
imports React (if your linting requires it) and exports a default Save component
that returns null (i.e., server-rendered no-client-save), matching the project's
style and export conventions; ensure any required ESLint or module headers are
present.

Comment on lines +53 to +56
a {
text-decoration: none;
color: var(--list-item-sytle, inherit);
display: inline-block;
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

Fix CSS custom property typo

--list-item-sytle is misspelled; it prevents the custom color from working.

Apply:

- color: var(--list-item-sytle, inherit);
+ color: var(--list-item-style, inherit);

Run to find all occurrences and ensure consistency:


🏁 Script executed:

#!/bin/bash
rg -n --type=css --type=scss --type=js --type=php --no-ignore -S '\-\-list-item-sy?tle'

Length of output: 28




🏁 Script executed:

#!/bin/bash
# Search for the misspelled custom property across all file types
# Using rg without the problematic type specification
rg -n -S 'list-item-sy' --glob='*.scss' --glob='*.css' --glob='*.js' --glob='*.php'

Length of output: 82389


🏁 Script executed:

#!/bin/bash
# Also check the specific file mentioned in the review
cat src/blocks/TableOfContents/style.scss | grep -n 'list-item'

Length of output: 47


🏁 Script executed:

#!/bin/bash
# Search for both spellings to understand which is used
rg -n 'list-item-style' --glob='*.scss' --glob='*.css' --glob='*.js' --glob='*.php'

Length of output: 0


Fix CSS custom property typo in two locations

The custom property --list-item-sytle is misspelled (should be --list-item-style), preventing the custom color from being applied.

Apply the fix in:

  1. src/blocks/TableOfContents/style.scss line 55:
- color: var(--list-item-sytle, inherit);
+ color: var(--list-item-style, inherit);
  1. src/blocks/TableOfContents/edit.js line 154:
- "--list-item-sytle": containerBackgroundColor,
+ "--list-item-style": containerBackgroundColor,
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
a {
text-decoration: none;
color: var(--list-item-sytle, inherit);
display: inline-block;
a {
text-decoration: none;
color: var(--list-item-style, inherit);
display: inline-block;
🤖 Prompt for AI Agents
In src/blocks/TableOfContents/style.scss around lines 53-56 and in
src/blocks/TableOfContents/edit.js at line 154, the CSS custom property name is
misspelled as --list-item-sytle; update both occurrences to --list-item-style so
the intended custom color is applied (search for the misspelled token and
replace it with the corrected property name in both files).

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 20

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

♻️ Duplicate comments (43)
src/blocks/components/TabSystem.js (3)

3-3: Remove unused Spacer import.

The __experimentalSpacer as Spacer import is never used in this component.

🔎 Proposed fix
-import { Button, ButtonGroup, __experimentalSpacer as Spacer } from '@wordpress/components';
+import { Button, ButtonGroup } from '@wordpress/components';

21-38: Add accessibility attributes for tab navigation.

The tab navigation is missing essential ARIA attributes for screen reader support. The ButtonGroup should have role="tablist", and each Button should have role="tab", aria-selected, and aria-controls attributes.

🔎 Proposed fix
-				<ButtonGroup>
+				<ButtonGroup role="tablist" aria-label={__('Block Settings Tabs', 'wedocs')}>
 					{tabs.map(tab => (
 						<Button
 							key={tab.key}
 							variant={activeTab === tab.key ? 'primary' : 'secondary'}
 							onClick={() => setActiveTab(tab.key)}
+							role="tab"
+							id={`wedocs-tab-${tab.key}`}
+							aria-selected={activeTab === tab.key}
+							aria-controls={`wedocs-tabpanel-${tab.key}`}
 							style={{
 								marginRight: '4px',
 								display: 'flex',
 								alignItems: 'center',
 								gap: '4px'
 							}}
 						>

43-55: Fix children handling, duplicate keys, and add accessibility attributes.

Three critical issues:

  1. Runtime error: children.map will break when a single child is passed (React children can be an object, not an array).
  2. Duplicate keys: All children after the first get key="style", causing React reconciliation issues.
  3. Missing accessibility: Tab panels need role="tabpanel", aria-labelledby, and corresponding id attributes.
🔎 Proposed fix

First, import Children from React:

-import { useState } from '@wordpress/element';
+import { useState, Children } from '@wordpress/element';

Then fix the content rendering:

 			{/* Tab Content */}
 			<div className="tab-content">
-				{children.map((child, index) => {
-					const tabKey = index === 0 ? 'setup' : 'style';
-					return (
-						<div
-							key={tabKey}
-							style={{
-								display: activeTab === tabKey ? 'block' : 'none'
-							}}
-						>
-							{child}
-						</div>
-					);
-				})}
+				{Children.toArray(children).map((child, index) => {
+					const tabKey = index === 0 ? 'setup' : 'style';
+					return (
+						<div
+							key={`${tabKey}-${index}`}
+							id={`wedocs-tabpanel-${tabKey}`}
+							role="tabpanel"
+							aria-labelledby={`wedocs-tab-${tabKey}`}
+							style={{
+								display: activeTab === tabKey ? 'block' : 'none'
+							}}
+						>
+							{child}
+						</div>
+					);
+				})}
 			</div>
src/blocks/TableOfContents/save.js (1)

1-3: The empty file issue from the previous review remains unresolved.

As noted in the previous review, this file contains only whitespace and serves no purpose. For server-rendered blocks, you should either implement it properly (returning null with proper imports like AdvanceContributors/save.js) or remove the file entirely.

assets/build/style-block-rtl.css (1)

1-1: Fix duplicate width property in source CSS.

A duplicate width property declaration exists in the selector .wedocs-search-input,.wedocs-editor-search-input. Since this is a build artifact, the issue should be resolved in the source CSS file before rebuilding.

🧰 Tools
🪛 Biome (2.1.2)

[error] 1-1: Duplicate properties can lead to unexpected behavior and may override previous declarations unintentionally.

Remove or rename the duplicate property to ensure consistent styling.

(lint/suspicious/noDuplicateProperties)

assets/build/block.js (1)

1-1: Address CSS custom property issue in TableOfContents source.

A previous review identified a typo and incorrect variable binding in the TableOfContents block source (src/blocks/TableOfContents/edit.js line 154). Since this is a build artifact, fix the source and rebuild.

src/blocks/Contributors/edit-old.js (1)

151-161: Preview ignores configured date format settings.

The date preview uses a hardcoded toLocaleDateString format and ignores the dateFormat and customDateFormat attributes that users can configure. This creates a mismatch between editor preview and frontend output.

Since PHP date format strings are specified in the help text, consider either:

  1. Using @wordpress/date utilities with format conversion
  2. Rendering a placeholder indicating the format will apply on frontend
src/blocks/AdvanceContributors/edit-old.js (2)

51-65: Replace wp.apiFetch with imported @wordpress/api-fetch.

This was flagged in a previous review. For bundled code, import apiFetch directly for better tree-shaking and explicit dependency management.


151-161: Date format preview ignores user settings.

This was flagged in a previous review. The preview hardcodes toLocaleDateString and ignores dateFormat/customDateFormat attributes.

assets/build/blocks/DocsGrid/index.asset.php (1)

1-1: Existing critical issue with react-jsx-runtime dependency already flagged.

The incompatibility between the react-jsx-runtime dependency (requires WP 6.6+) and the plugin's minimum WordPress requirement (5.6+) has already been identified in a previous review comment. Please address that issue before merging.

includes/Assets.php (1)

85-89: Critical: Style handle enqueued without registration (duplicate issue).

The wedocs-block-style registration remains commented out (lines 85-89), but the style is still enqueued at lines 129 and 155. This is the same critical issue flagged in the previous review and must be resolved.

Apply one of the fixes from the previous review:

Option 1: Uncomment and fix the registration:

🔎 Restore registration
-            // wp_register_style(
-            //     'wedocs-block-style',
-            //     $assets_url . '/build/style-block.css',
-            //     $block_dependencies['version']
-            // );
+            wp_register_style(
+                'wedocs-block-style',
+                $assets_url . '/build/style-block.css',
+                array(),
+                $block_dependencies['version']
+            );

Option 2: Remove all enqueue calls:

🔎 Remove enqueue calls
-        wp_enqueue_style( 'wedocs-block-style' );

And in admin_enqueue:

     public function admin_enqueue() {
-        wp_enqueue_style( 'wedocs-block-style' );
-
         // Enqueue admin script.

Also applies to: 129-129, 155-155

src/blocks/TableOfContents/controls/ListItems.js (1)

7-16: Critical: Undefined variable reference (duplicate issue).

The component uses containerBackgroundColor on line 14 without defining it. This is the same critical issue from the previous review and will cause a ReferenceError at runtime.

Apply one of the fixes from the previous review:

Option 1: Destructure from attributes:

🔎 Destructure the variable
 const ListItems = ({ attributes, setAttributes }) => {
+    const { containerBackgroundColor } = attributes;
+    
     return (
         <PanelBody title={__('List Items', 'dynamic-table-of-contents-block-wp')} initialOpen={false}>

Option 2: Access via attributes:

🔎 Use attributes.containerBackgroundColor
             <div style={{ marginBottom: '20px' }}>
                 <label>{__('Background Color', 'dynamic-table-of-contents-block-wp')}</label>
                 <ColorPicker
-                    color={containerBackgroundColor}
+                    color={attributes.containerBackgroundColor}
                     onChange={(value) => setAttributes({ containerBackgroundColor: value })}
                 />
assets/build/blocks/TableOfContents/style-index.css (1)

1-1: Accessibility issue: Loading message in CSS pseudo-element (previously flagged).

As noted in the previous review, the .toc-loading .toc-content:after rule renders "Loading headings..." via a CSS pseudo-element, which is not accessible to screen readers. This loading message should be moved to the DOM with role="status" or aria-live="polite" to ensure it's announced by assistive technologies.

assets/build/blocks/TableOfContents/style-index-rtl.css (1)

1-1: Accessibility issue: Loading message in CSS pseudo-element (previously flagged in RTL variant).

The same accessibility issue noted in the LTR version applies here: the loading message in .toc-loading .toc-content:after should be moved to the DOM with appropriate ARIA attributes for screen reader support.

assets/build/store.js (1)

1-1: Static analysis errors remain unaddressed.

The unsafe optional chaining and switch clause issues flagged by static analysis are still present in this build artifact. These were previously identified in the source files (src/data/docs/reducer.js around lines 84-85). The source must be fixed and the bundle rebuilt.

src/blocks/TableOfContents/ColorsControls.js (3)

17-20: Undefined colorsControls will crash the component.

The destructuring of colorsControls without a default value and immediate access to colorsControls[device] will throw a TypeError if attributes.colorsControls is undefined.


53-53: Incorrect text domain breaks translations.

The text domain 'block-responsive' should be 'wedocs' to match this plugin's translation infrastructure. This issue appears throughout the file at multiple locations.

Also applies to: 68-68, 108-108, 122-122, 135-135, 158-158, 174-174, 229-229, 243-243, 257-257, 280-280, 293-293, 326-326


322-347: Button.text prop may not be supported in all versions.

Using the text prop on Button can cause compatibility issues with some versions of @wordpress/components. The label should be passed as children instead.

src/blocks/commonControls/TypographyControls.js (1)

28-30: Undefined typographyControls will crash the component.

Destructuring without a default and accessing typographyControls[device] will throw if attributes.typographyControls is undefined.

src/blocks/commonControls/AlignmentControls.js (2)

26-28: Guard against undefined alignmentControls to avoid runtime errors

attributes.alignmentControls may be undefined; accessing alignmentControls[device] will throw. This was flagged in a previous review.

🔎 Proposed fix
 const AlignmentControls = ({ attributes, setAttributes, device }) => {
-	const { alignmentControls } = attributes;
-	const currentAlignment = alignmentControls[device] || {};
+	const { alignmentControls = {} } = attributes;
+	const currentAlignment = alignmentControls[device] || {};

161-165: Invalid CSS value for alignItems: "space-between" is not valid

align-items does not accept space-between; that's a justify-content value. This will produce invalid CSS. This was flagged in a previous review.

🔎 Proposed fix
 <ToggleGroupControlOptionIcon
-	value="space-between"
-	label={__('Space between', 'wedocs')}
+	value="stretch"
+	label={__('Stretch', 'wedocs')}
 	icon={justifyStretchVertical}
 />
assets/build/blocks/DocsGrid/render.php (1)

74-82: Guard against non-array padding/margin inputs

If $grid_padding is not an array, accessing ['top'] etc. will emit "Illegal string offset" notices. This was flagged in a previous review.

🔎 Proposed fix
-        if ($grid_padding) {
+        if ( is_array( $grid_padding ) ) {
             $padding_style = sprintf(
                 'padding: %s %s %s %s;',
                 esc_attr($grid_padding['top'] ?? '1.5rem'),

Apply the same pattern to $grid_margin, $button_padding, and $button_margin checks.

src/blocks/commonControls/DisplayControls.js (2)

50-57: Guard against undefined displayControls

If attributes.displayControls is undefined, line 53-54 and line 61 will throw runtime errors. This was flagged in a previous review.

🔎 Proposed fix
 const toggleDeviceVisibility = (deviceKey) => {
+	const current = attributes.displayControls || {};
 	setAttributes({
 		displayControls: {
-			...attributes.displayControls,
-			[deviceKey]: !attributes.displayControls[deviceKey],
+			...current,
+			[deviceKey]: !current[deviceKey],
 		},
 	});
 };

 // Render individual device control card
 const renderDeviceCard = ({ key, icon, label }) => {
-	const isHidden = attributes.displayControls[key];
+	const isHidden = attributes.displayControls?.[key];

Also applies to: 61-61


76-80: Add aria-label for accessibility

The toggle button displays only an icon, making it inaccessible to screen reader users. This was flagged in a previous review.

🔎 Proposed fix
 <Button
 	__next40pxDefaultSize
 	onClick={() => toggleDeviceVisibility(key)}
 	icon={isHidden ? unseen : seen}
+	aria-label={
+		isHidden
+			? __('Show on', 'wedocs') + ' ' + key
+			: __('Hide on', 'wedocs') + ' ' + key
+	}
 />
src/blocks/Contributors/render.php (5)

100-106: Wrong API for retrieving contributors - uses get_post_field instead of post meta

get_post_field('wedocs_contributors', ...) reads a posts table column, not post meta. For main_author case, this should use post_author field. This was flagged in a previous review.

🔎 Proposed fix
         case 'main_author':
-            $author_id = get_post_field('wedocs_contributors', $post->ID);
+            if ( ! $post ) { break; }
+            $author_id = get_post_field('post_author', $post->ID);
             if ($author_id) {
                 $contributors[] = get_userdata($author_id);
             }
             break;

120-131: Invalid contributor retrieval in 'all' case

get_post_field('wedocs_contributors', ...) returns a string column, not post meta. Calling array_values() on it produces an array of characters, causing incorrect behavior. This was flagged in a previous review.

🔎 Proposed fix
         case 'all':
         default:
             // Get all contributors who have edited the post
-            $author_id = get_post_field('wedocs_contributors', $post->ID);
-            $authors = array_values($author_id); // return auhtors id.
-            foreach($authors as $author){
-                $contributors[]= get_userdata($author);
-            }
-
-
-            if ($author_id && ($author_user = get_userdata($author_id))) {
-                $contributors[] = $author_user;
-            }
+            // Include post author first
+            $post_author_id = $post ? (int) get_post_field('post_author', $post->ID) : 0;
+            if ( $post_author_id && ($author_user = get_userdata($post_author_id)) ) {
+                $contributors[] = $author_user;
+            }
+
+            // Get contributors from post meta
+            $author_ids = (array) get_post_meta($post->ID, 'wedocs_contributors', true);
+            foreach ( $author_ids as $uid ) {
+                if ( $user = get_userdata( (int) $uid ) ) {
+                    $contributors[] = $user;
+                }
+            }

156-165: Demo fallback should not render in production

This creates a fake "Demo Author" user on production sites when no contributors are found. This was flagged in a previous review.

🔎 Proposed fix
-        if (empty($contributors)) {
-            // For demo purposes, add mock contributors if none found
-            $contributors = [
-                (object) [
-                    'ID' => 1,
-                    'display_name' => 'Demo Author',
-                    'user_email' => 'demo@example.com'
-                ]
-            ];
-        }
+        if (empty($contributors)) {
+            return '';
+        }

395-395: Return markup instead of echoing

Block render callbacks should return the output string, not echo it. Echoing can cause misplaced output. This was flagged in a previous review.

🔎 Proposed fix
-    echo render_wedocs_contributors_block($attributes, $content, $block);
+    return render_wedocs_contributors_block($attributes, $content, $block);
 }

Note: The echo should be moved outside the function_exists block and removed entirely since the function already returns the output.


153-154: De-duplicate contributors list

array_filter removes nulls but doesn't prevent duplicate users (e.g., if post author also appears in revisions). This was flagged in a previous review.

🔎 Proposed fix
         // Filter out invalid contributors
-        $contributors = array_filter($contributors);
+        $contributors = array_filter($contributors);
+        // De-duplicate by user ID
+        $contributors = array_values(array_reduce($contributors, function($acc, $u) {
+            if (is_object($u) && isset($u->ID)) {
+                $acc[$u->ID] = $u;
+            }
+            return $acc;
+        }, []));
assets/build/blocks/AdvanceContributors/render.php (4)

49-57: Critical: Unsafe $post property access without null check.

Lines 50 and 73 access $post->ID without verifying that $post is not null. This will cause a fatal error in non-singular contexts (archives, previews, etc.).

🔎 Required fix
 case 'main_author':
+	if (!$post) { break; }
 	$author_id = get_post_field('post_author', $post->ID);

Apply the same null guard at Line 73 and anywhere else $post->ID is accessed.

Based on past review comments.


229-242: Major: Box shadow key mismatch prevents shadows from rendering.

Line 230 checks for $shadow['x'] but the block attributes schema (block.json lines 284-290) provides 'horizontal' and 'vertical' keys. This mismatch means box shadows will never apply.

🔎 Required fix
-if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['x'])) {
+if (isset($controls['boxShadow']) && is_array($controls['boxShadow']) && isset($controls['boxShadow']['horizontal'])) {
 	$shadow = $controls['boxShadow'];
 	$shadow_value = '';
 	if (isset($shadow['inset']) && $shadow['inset']) {
 		$shadow_value .= 'inset ';
 	}
-	$shadow_value .= esc_attr($shadow['x']) . ' ';
-	$shadow_value .= esc_attr($shadow['y']) . ' ';
+	$shadow_value .= esc_attr($shadow['horizontal']) . ' ';
+	$shadow_value .= esc_attr($shadow['vertical']) . ' ';

Based on past review comments.


333-345: Critical: Inverted hide-class logic hides block on all devices.

Lines 335-342 add wedocs-hide-{device} classes whenever the device key exists (which is always true per the schema defaults), causing the block to be hidden across all breakpoints.

🔎 Required fix

Only add hide classes when display is explicitly set to 'none':

-if (isset($display_controls['desktop']) && $display_controls['desktop']) {
+if (isset($display_controls['desktop']['display']) && $display_controls['desktop']['display'] === 'none') {
 	$display_classes[] = 'wedocs-hide-desktop';
 }
-if (isset($display_controls['tablet']) && $display_controls['tablet']) {
+if (isset($display_controls['tablet']['display']) && $display_controls['tablet']['display'] === 'none') {
 	$display_classes[] = 'wedocs-hide-tablet';
 }
-if (isset($display_controls['mobile']) && $display_controls['mobile']) {
+if (isset($display_controls['mobile']['display']) && $display_controls['mobile']['display'] === 'none') {
 	$display_classes[] = 'wedocs-hide-mobile';
 }

Based on past review comments.


497-499: Critical: Render file must return the generated HTML.

Line 499 calls the render function but doesn't return its output to WordPress, resulting in empty block output on the frontend.

🔎 Required fix
 	return $output;
 }
-render_wedocs_advance_contributors_block( $attributes, $content, $block );
+return render_wedocs_advance_contributors_block( $attributes, $content, $block );

Based on past review comments.

assets/build/blocks/AdvanceContributors/block.json (1)

284-291: Schema mismatch with render.php for box shadow.

The block.json schema correctly defines box shadow with "horizontal" and "vertical" keys, but the render.php file (Line 230) checks for "x" and "y", causing shadows to never render.

The fix should be applied in render.php to match this schema. See the review comment on render.php lines 229-242.

Based on past review comments.

assets/build/blocks/TableOfContents/index.js (1)

1-1: Reconsider committing minified build artifacts to the repository.

This is generated build output that should not be committed to version control. See the previous comment on assets/build/blocks/AdvanceContributors/index.js for the same rationale.

src/blocks/commonControls/DimensionsControls.js (3)

11-14: Guard against undefined dimensionsControls to prevent runtime errors.

dimensionsControls may be undefined, causing dimensionsControls[device] to throw a runtime error.

🔎 Proposed fix
-const DimensionsControls = ({ attributes, setAttributes, device }) => {
-	const { dimensionsControls } = attributes;
-	const currentDimensions = dimensionsControls[device] || {};
+const DimensionsControls = ({ attributes, setAttributes, device }) => {
+	const { dimensionsControls = {} } = attributes;
+	const currentDimensions = dimensionsControls[device] || {};

Based on past review comments.


15-28: Guard nested object spreads to prevent runtime errors.

Spreading currentDimensions.padding will throw if padding is undefined.

🔎 Proposed fix
 const handlePaddingChange = (value) => {
 	const newDimensionsControls = {
 		...dimensionsControls,
 		[device]: {
 			...currentDimensions,
 			padding: {
-				...currentDimensions.padding,
+				...(currentDimensions.padding ?? {}),
 				...value,
 			},
 		},
 	};
 
 	setAttributes({ dimensionsControls: newDimensionsControls });
 };

Apply the same pattern to handleMarginChange (lines 30-43) and handleBlockSpacingChange (lines 45-58).

Based on past review comments.


69-74: Replace -Infinity with a supported numeric value.

Gutenberg's SpacingSizesControl expects a finite number for minimumCustomValue. Using -Infinity is not supported and may break UI validation.

🔎 Proposed fix
 <SpacingSizesControl
 	values={currentDimensions.margin || {}}
 	onChange={handleMarginChange}
 	label={__('Margin', 'wedocs')}
-	minimumCustomValue={-Infinity}
+	minimumCustomValue={-1000}
 />

Alternatively, omit the prop to use the component's default minimum value.

Based on past review comments.

src/blocks/TableOfContents/style.scss (1)

53-56: Fix CSS custom property typo.

The custom property name is misspelled as --list-item-sytle (should be --list-item-style), which prevents the custom color from being applied.

🔎 Proposed fix
 a {
 	text-decoration: none;
-	color: var(--list-item-sytle, inherit);
+	color: var(--list-item-style, inherit);
 	display: inline-block;
 	transition: color 0.2s ease;

Note: According to past review comments, this typo also appears in the corresponding edit.js file where the CSS variable is set. Ensure both locations are fixed for consistency.

Based on past review comments.

src/blocks/commonControls/ColorsControls.js (1)

17-19: Add missing device prop to function signature.

The component references device on line 19 but doesn't receive it as a prop, causing colorsControls[device] to be undefined.

🔎 Proposed fix
-const ColorsControls = ({ attributes, setAttributes, isTextColor = false, isBackgroundColor = false, isLinkColor = false }) => {
-	const { colorsControls } = attributes;
+const ColorsControls = ({ attributes, setAttributes, device, isTextColor = false, isBackgroundColor = false, isLinkColor = false }) => {
+	const { colorsControls = {} } = attributes;
 	const currentColors = colorsControls[device] || {};

Additionally, consider providing a default value for device (e.g., device = 'desktop') if it's optional.

Based on past review comments.

src/blocks/commonControls/BackgroundImageControls.js (1)

164-182: UnitControl: "auto" is invalid for __experimentalUnitControl.

__experimentalUnitControl expects a numeric value with unit. Passing "auto" will cause validation issues. Use empty string and add explicit units.

This was flagged in a previous review. The fix should use an empty string as the default and define allowed units:

 <UnitControl
     __next40pxDefaultSize
-    value={currentBackgroundImage.bgWidth || 'auto'}
+    value={currentBackgroundImage.bgWidth ?? ''}
+    units={[
+        { value: 'px', label: 'px' },
+        { value: '%', label: '%' },
+    ]}
     disabled={currentBackgroundImage.bgSize !== 'tile'}
     onChange={(value) => { ... }}
     placeholder={__('Auto', 'wedocs')}
 />
src/blocks/helpers/block-styles.php (2)

58-70: CSS value sanitization function exists but is not used.

The wedocs_sanitize_css_value() function (lines 290-312) provides proper CSS value sanitization, but wedocs_build_spacing_styles() uses only esc_attr() which doesn't validate CSS units. This was previously flagged and the sanitization function was added, but integration is incomplete.

The fix from the past review should be applied here to use wedocs_sanitize_css_value() for padding/margin values.


81-101: Border style and radius values lack proper sanitization.

This segment uses esc_attr() for CSS values but doesn't validate against allowed units. The wedocs_sanitize_css_value() function exists but isn't used here.

🟡 Minor comments (21)
readme.md-23-39 (1)

23-39: Clarify the purpose and placement of the Mozart configuration block.

This commented-out configuration block appears to be for the Mozart dependency system, but it's unclear why this needs to be in a README file. Additionally, the namespace (WPMUDEV_PluginTest) and classmap prefix suggest this may be example or copied configuration, not specific to weDocs.

Consider:

  • Moving actual configuration to proper config files (e.g., composer.json or a dedicated Mozart config file)
  • If this is documentation, provide context explaining what Mozart is and why weDocs uses it
  • Removing the commented block if it's example code that's not relevant to this project
src/blocks/components/SpacingControl.js-73-85 (1)

73-85: Fallback logic may override intentional '0px' gap values.

The expression gapValue || '10px' on Line 77 will default to '10px' for any falsy value, including '0px', 0, or ''. If a developer explicitly wants to set the gap to zero, this fallback will prevent it.

🔎 Proposed fix using nullish coalescing
 			<UnitControl
 				label={__('Gap', 'wedocs')}
-				value={gapValue || '10px'}
+				value={gapValue ?? '10px'}
 				onChange={onGapChange}
 				units={[
 					{ value: 'px', label: 'px' },

This ensures only null or undefined trigger the default, allowing explicit '0px' or 0 values.

src/blocks/components/SpacingControl.js-1-7 (1)

1-7: Update imports to use stable BoxControl and UnitControl exports.

__experimentalBoxControl and __experimentalUnitControl were promoted to stable APIs (BoxControl and UnitControl) in WordPress 6.7/6.8. Update the imports to:

import { BoxControl, UnitControl } from '@wordpress/components';

The __experimentalSpacer import should remain as-is, as Spacer has not been stabilized yet.

src/blocks/commonControls/BorderAndShadowControls.js-215-237 (1)

215-237: Inconsistent reset values for different properties.

The reset operation uses different values for each property:

  • border: {} (empty object)
  • borderRadius: null (null)
  • boxShadow: {} (empty object)

While this works due to the fallback logic on line 97, the inconsistency could confuse maintainers.

🔎 Suggested fix for consistency
 				onClick={() => {
 					setAttributes({
 						borderAndShadowControls: {
 							...borderAndShadowControls,
 							[device]: {
 								...currentBorderAndShadow,
-								border: {},
-								borderRadius: null,
-								boxShadow: {},
+								border: undefined,
+								borderRadius: undefined,
+								boxShadow: undefined,
 							},
 						},
 					});

Or consistently use empty objects:

-								borderRadius: null,
+								borderRadius: {},
assets/build/print-rtl.css-141-144 (1)

141-144: Duplicate selector a:not(.anchorjs-link)::after.

The same selector appears twice on consecutive lines. This is likely a copy-paste error.

🔎 Proposed fix
-a:not(.anchorjs-link)::after,
-a:not(.anchorjs-link)::after {
+a:not(.anchorjs-link)::after {
   content: ' (' attr(href) ')';
 }
src/blocks/helpers/block-helpers.js-374-389 (1)

374-389: isBreakpoint will throw in SSR/Node environments.

Direct access to window.innerWidth without a guard will cause a ReferenceError during server-side rendering or testing in Node. Add a check for window existence.

🔎 Proposed fix
 export const isBreakpoint = (breakpoint) => {
+	if (typeof window === 'undefined') {
+		return false;
+	}
 	const breakpoints = getBreakpoints();
 	const width = window.innerWidth;
assets/build/print-rtl.css-55-62 (1)

55-62: Duplicate font-size declarations in the same rule.

font-size is declared twice (line 55: 18px, line 62: 15px). The second declaration overrides the first, making line 55 dead code. If 15px is the intended size, remove line 55.

🔎 Proposed fix
 .entry-content dl dt {
   float: right;
   display: inline-block;
   font-weight: 400;
   text-align: center;
   padding: 4px 9px;
   margin-bottom: 1em;
-  font-size: 18px;
   line-height: 1.2em;
   border-radius: 50px;
   color: #fff;
   background: #3197d1;
   vertical-align: baseline;
   white-space: nowrap;
   font-size: 15px;
src/blocks/TableOfContents/index.js-29-34 (1)

29-34: Add save: () => null to the block registration.

The block registration is missing the save property. Based on the pattern used in Contributors and AdvanceContributors blocks (which also use server-side rendering via render.php), add:

save: () => null,

This indicates that the block content is rendered server-side rather than stored in the database.

src/blocks/commonControls/TypographyControls.js-244-271 (1)

244-271: Use children for Button label instead of text prop.

The text prop on Button may not be supported in all versions of @wordpress/components. Pass the label as children for better compatibility.

🔎 Proposed fix
 <Button
 	__next40pxDefaultSize
 	variant="secondary"
 	isDestructive
-	text={__('Reset All', 'wedocs')}
 	style={{
 		width: '100%',
 		justifyContent: 'center',
 		marginTop: '16px',
 	}}
 	onClick={() => {
 		setAttributes({
 			typographyControls: {
 				...typographyControls,
 				[device]: {
 					...currentTypography,
 					fontFamily: null,
 					fontSize: null,
 					fontAppearance: null,
 					lineHeight: null,
 					letterSpacing: null,
 					textDecoration: null,
 					textTransform: null,
 				},
 			},
 		});
 	}}
-/>
+>
+	{__('Reset All', 'wedocs')}
+</Button>
src/blocks/Contributors/render.php-332-332 (1)

332-332: Use wp_date() instead of date() for timezone-aware formatting

date() doesn't respect WordPress timezone settings. Use wp_date() for consistent timezone handling.

🔎 Proposed fix
-            $last_modified = $post ? get_the_modified_date($date_format_string, $post) : date($date_format_string);
+            $last_modified = $post ? get_the_modified_date($date_format_string, $post) : wp_date($date_format_string);
src/blocks/Contributors/edit.js-323-327 (1)

323-327: Hardcoded date format in preview.

The preview always uses 'en-US' locale and a specific format, ignoring the attributes.dateFormat and attributes.customDateFormat settings. This creates a mismatch between the editor preview and the actual rendered output.

Consider using the configured date format settings to make the preview more accurate, or add a comment explaining this is a simplified preview.

assets/build/frontend-rtl.css-508-515 (1)

508-515: Remove duplicate font-size declaration.

Line 508 declares font-size: 18px and line 515 declares font-size: 15px for the same selector. This creates ambiguity about which size should be applied.

🔎 Proposed fix
   padding: 4px 9px;
   margin-bottom: 1em;
-  font-size: 18px;
   line-height: 1.2em;
   border-radius: 50px;
   color: #fff;
   background: #3197d1;
   vertical-align: baseline;
   white-space: nowrap;
   font-size: 15px;
src/blocks/AdvanceContributors/render.php-454-454 (1)

454-454: Incorrect date fallback when post is unavailable.

Line 454 uses date($date_format_string) as fallback when $post is unavailable, which returns the current date/time rather than a meaningful post date. Consider omitting the date section entirely when the post is unavailable.

🔎 Proposed fix
-        $last_modified = $post ? get_the_modified_date($date_format_string, $post) : date($date_format_string);
+        $last_modified = $post ? get_the_modified_date($date_format_string, $post) : '';
+        
+        if (!$last_modified) {
+            // Skip rendering date if post is unavailable
+            $show_last_updated = false;
+        }

Committable suggestion skipped: line range outside the PR's diff.

src/blocks/DocsGrid/render.php-183-184 (1)

183-184: Unused variable $total_pages and missing pagination rendering.

$total_pages is computed but never used. The get_pagination_style_tag function exists but pagination UI is not rendered. Either implement pagination or remove the unused code.

Also applies to: 207-212

src/blocks/TableOfContents/edit.js-113-113 (1)

113-113: Potential negative indent when h1 is included in supportedHeadings.

The counters object starts at level 2, and indent calculation (heading.level - 2) * 20 produces negative values for h1. If h1 is supported, this could cause layout issues.

🔎 Proposed fix
-		let counter = 1;
-		const counters = { 2: 0, 3: 0, 4: 0, 5: 0 };
+		let counter = 1;
+		const counters = { 1: 0, 2: 0, 3: 0, 4: 0, 5: 0 };

And for indent:

-				const indent = showHierarchy ? (heading.level - 2) * 20 : 0;
+				const indent = showHierarchy ? Math.max(0, (heading.level - 1) * 20) : 0;

Also applies to: 130-130

assets/build/blocks/Contributors/render.php-332-332 (1)

332-332: Use wp_date() instead of date() for WordPress timezone handling.

date() uses server timezone, not the WordPress configured timezone. Use wp_date() for consistency with WordPress settings.

🔎 Proposed fix
-            $last_modified = $post ? get_the_modified_date($date_format_string, $post) : date($date_format_string);
+            $last_modified = $post ? get_the_modified_date($date_format_string, $post) : wp_date($date_format_string);
src/blocks/TableOfContents/edit.js-154-154 (1)

154-154: Fix typo in CSS variable name: --list-item-sytle--list-item-style.

This typo will cause the CSS variable to not match any references expecting --list-item-style.

🔎 Proposed fix
         style: {
-            "--list-item-sytle": containerBackgroundColor,
+            "--list-item-style": containerBackgroundColor,
src/blocks/DocsGrid/render.php-176-178 (1)

176-178: Use integer -1 instead of string '-1' for posts_per_page.

WP_Query expects an integer for posts_per_page. Using a string may cause unexpected behavior.

🔎 Proposed fix
         } else {
-            $args['posts_per_page'] = '-1';
+            $args['posts_per_page'] = -1;
             $args['paged'] = 1;
         }
src/blocks/AdvanceContributors/edit.js-286-290 (1)

286-290: Avoid Math.random() as React key.

Using Math.random() for keys (line 289 fallback) causes React to unmount and remount components on every render, degrading performance and breaking state.

🔎 Suggested fix
-						const contributorId = contributor.id || contributor.ID || Math.random();
+						const contributorId = contributor.id || contributor.ID || `fallback-${index}`;

Note: This requires adding index parameter to the .map() callback.

Committable suggestion skipped: line range outside the PR's diff.

src/blocks/helpers/block-styles.php-222-225 (1)

222-225: Custom styles are merged without validation.

The $args['custom'] array is directly merged into styles without any sanitization. If this array contains user-controlled values, it could allow CSS injection.

🔎 Suggested fix
     // Custom styles
     if (isset($args['custom']) && is_array($args['custom'])) {
-        $styles = array_merge($styles, $args['custom']);
+        $sanitized_custom = array_map('sanitize_text_field', $args['custom']);
+        $styles = array_merge($styles, $sanitized_custom);
     }
package.json-30-30 (1)

30-30: Test the build thoroughly after upgrading @wordpress/scripts to v30.

The upgrade from @wordpress/scripts v25 to v30.15.0 includes changes to webpack, Babel, and ESLint presets. Review the changelog for breaking changes specific to your setup, run your build scripts, and verify that blocks render correctly in WordPress. The version of @wordpress/block-editor does not need to be bumped solely based on this upgrade—WordPress packages use a dist-tag strategy (e.g., @wordpress/block-editor@wp-6.x) for version coordination rather than strict pinning.

@@ -0,0 +1 @@
<?php return array('dependencies' => array('react-jsx-runtime', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-i18n', 'wp-primitives'), 'version' => 'f2d62c10206d682dc7b2');
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

echo "=== Checking for build artifacts in assets/build/ ==="
if [ -d assets/build ]; then
    find assets/build -type f | head -20
else
    echo "assets/build/ directory not found"
fi

echo -e "\n=== Checking git status of assets/build/ ==="
git ls-files assets/build/ 2>/dev/null | head -20 || echo "No git-tracked files in assets/build/"

echo -e "\n=== Checking .gitignore for build directory exclusions ==="
if [ -f .gitignore ]; then
    echo "=== Full .gitignore content ==="
    cat -n .gitignore
    echo ""
    echo "=== Patterns matching 'build' or 'assets' ==="
    grep -n "build\|dist\|assets" .gitignore || echo "No matching patterns found"
else
    echo ".gitignore file not found"
fi

echo -e "\n=== Checking for build-related files (package.json, etc.) ==="
if [ -f package.json ]; then
    echo "=== package.json found, checking for build scripts ==="
    head -50 package.json
fi

echo -e "\n=== Git status overview for assets/build/ ==="
git status assets/build/ 2>/dev/null || echo "Git status check failed"

Repository: weDevsOfficial/wedocs-plugin

Length of output: 4514


Remove build artifacts from version control and add assets/build/ to .gitignore.

The assets/build/ directory contains auto-generated files created by wp-scripts build and is currently tracked in git. These artifacts should not be committed because they:

  • Cause merge conflicts when multiple developers build locally
  • Bloat the repository with auto-generated content
  • Create unnecessary churn in the version history

Add assets/build/ to .gitignore and regenerate these assets during the build/deployment process (e.g., via the npm run build or npm run release scripts).

🤖 Prompt for AI Agents
In assets/build/blocks/AdvanceContributors/index.asset.php at line 1, a
generated build artifact is committed; remove all files under assets/build/ from
version control and add assets/build/ to .gitignore so generated assets aren’t
tracked. Specifically: delete the committed assets/build/ files from the repo
(git rm --cached or remove and commit), add an entry "assets/build/" to
.gitignore, and ensure the build step (npm run build/release) generates these
files during CI or deployment instead of committing them.

@@ -0,0 +1 @@
.contributors-tab-system .components-button-group{display:flex}.wedocs-contributors .contributors-container{display:flex;align-items:center;flex-wrap:wrap;gap:10px;margin-bottom:10px}@media(max-width: 768px){.wedocs-contributors .contributors-container{flex-direction:column;align-items:flex-start;gap:8px}}.wedocs-contributors .contributors-container .contributor-item{display:flex;align-items:center;gap:8px}@media(max-width: 768px){.wedocs-contributors .contributors-container .contributor-item{width:100%}}.wedocs-contributors .contributors-container .contributor-item .contributor-avatar{display:flex;align-items:center;justify-content:center;transition:all .3s ease}.wedocs-contributors .contributors-container .contributor-item .contributor-avatar.avatar-hover:hover{transform:scale(1.1);box-shadow:0 2px 8px rgba(0,0,0,.15)}.wedocs-contributors .contributors-container .contributor-item .contributor-avatar img{display:block;-o-object-fit:cover;object-fit:cover}.wedocs-contributors .contributors-container .contributor-item .contributor-avatar .default-icon{display:flex;align-items:center;justify-content:center;background-color:#0073aa;color:#fff}.wedocs-contributors .contributors-container .contributor-item .contributor-avatar .default-icon svg{width:60%;height:60%;fill:currentColor}.wedocs-contributors .contributors-container .contributor-item .contributor-name{transition:color .3s ease;text-decoration:none}.wedocs-contributors .contributors-container .contributor-item .contributor-name:hover{text-decoration:underline}.wedocs-contributors .contributors-container .contributor-item .contributor-name.no-link{cursor:default}.wedocs-contributors .last-updated{margin-top:10px;font-style:italic}@media(max-width: 768px){.wedocs-contributors .last-updated{margin-top:8px;font-size:.9em}}.wedocs-contributors .contributors-title{margin:0 0 10px 0;font-weight:600;font-size:16px}@media(max-width: 480px){.wedocs-contributors .contributors-container{gap:6px}.wedocs-contributors .contributors-container .contributor-item{gap:6px}.wedocs-contributors .contributors-container .contributor-item .contributor-avatar img,.wedocs-contributors .contributors-container .contributor-item .contributor-avatar .default-icon{width:28px !important;height:28px !important}.wedocs-contributors .contributors-container .contributor-item .contributor-name{font-size:.9em}.wedocs-contributors .last-updated{font-size:.8em}}@media(prefers-contrast: high){.wedocs-contributors .contributor-item .contributor-avatar{border:2px solid currentColor !important}.wedocs-contributors .contributor-item .contributor-name{text-decoration:underline}}@media(prefers-reduced-motion: reduce){.wedocs-contributors .contributor-avatar{transition:none !important}.wedocs-contributors .contributor-avatar.avatar-hover:hover{transform:none !important}.wedocs-contributors .contributor-name{transition:none !important}}@media(prefers-color-scheme: dark){.wedocs-contributors .contributor-item .contributor-avatar .default-icon{background-color:#4a90a4}}@media print{.wedocs-contributors .contributors-container{flex-direction:column;align-items:flex-start}.wedocs-contributors .contributor-item .contributor-avatar{display:none}}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Compare LTR and RTL versions to verify they're different

echo "=== Comparing AdvanceContributors LTR and RTL files ==="
if [ -f assets/build/blocks/AdvanceContributors/style-index.css ] && [ -f assets/build/blocks/AdvanceContributors/style-index-rtl.css ]; then
  echo "File sizes:"
  wc -c assets/build/blocks/AdvanceContributors/style-index*.css
  echo ""
  echo "Diff output (first 50 lines):"
  diff assets/build/blocks/AdvanceContributors/style-index.css assets/build/blocks/AdvanceContributors/style-index-rtl.css | head -50
else
  echo "Files not found - listing directory:"
  find assets/build/blocks/AdvanceContributors -type f -name "*.css" 2>/dev/null || echo "Directory not found"
fi

echo ""
echo "=== Checking for RTL-specific properties in AdvanceContributors RTL file ==="
if [ -f assets/build/blocks/AdvanceContributors/style-index-rtl.css ]; then
  echo "Searching for directional properties:"
  grep -o "padding-right\|border-right\|margin-right\|float" assets/build/blocks/AdvanceContributors/style-index-rtl.css | sort | uniq -c
else
  echo "RTL file not found"
fi

echo ""
echo "=== Checking TableOfContents RTL file for reference ==="
if [ -f assets/build/blocks/TableOfContents/style-index-rtl.css ]; then
  echo "Size of TableOfContents RTL file:"
  wc -c assets/build/blocks/TableOfContents/style-index-rtl.css
  echo ""
  echo "Searching for directional properties in TableOfContents RTL:"
  grep -o "padding-right\|border-right\|margin-right\|float" assets/build/blocks/TableOfContents/style-index-rtl.css | head -10
else
  echo "TableOfContents RTL file not found"
fi

Repository: weDevsOfficial/wedocs-plugin

Length of output: 684


RTL stylesheet is identical to LTR version and missing directional adjustments.

The style-index-rtl.css file is byte-for-byte identical to style-index.css (both 3204 bytes with no differences). RTL stylesheets require directional properties adjustments such as:

  • padding-right instead of padding-left (and vice versa)
  • border-right instead of border-left
  • margin-right instead of margin-left
  • Adjusted float and text-align values

The TableOfContents RTL variant correctly implements these adjustments. Apply equivalent RTL transformations to the AdvanceContributors stylesheet.

🤖 Prompt for AI Agents
In assets/build/blocks/AdvanceContributors/style-index-rtl.css around lines 1 to
1, the RTL file is identical to the LTR stylesheet and lacks directional
mirroring; update the CSS to mirror directional properties from the LTR file —
replace left/right properties (padding-left ↔ padding-right, margin-left ↔
margin-right, border-left ↔ border-right), invert float and text-align values,
and adjust directional shorthands (e.g., margin: top right bottom left -> swap
left/right), ensure any directional transform/translateX values are negated, and
follow the same RTL adjustments used in the TableOfContents RTL variant so
layout, alignment and visual ordering are correct for right-to-left languages.

Comment on lines +11 to +12
if ( !function_exists('render_wedocs_contributors_block')){
function render_wedocs_contributors_block($attributes, $content, $block) {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Render function called inside function_exists guard.

The echo render_wedocs_contributors_block(...) at line 395 is inside the guard, so it only executes on first load. Typically, the function should be defined inside the guard, but called outside.

🔎 Proposed fix
     return $output;
-    }
-    echo render_wedocs_contributors_block($attributes, $content, $block);
 }
+}
+
+echo render_wedocs_contributors_block($attributes, $content, $block);

Also applies to: 395-396

🧰 Tools
🪛 PHPMD (2.15.0)

12-12: Avoid unused parameters such as '$content'. (undefined)

(UnusedFormalParameter)


12-12: Avoid unused parameters such as '$block'. (undefined)

(UnusedFormalParameter)

🤖 Prompt for AI Agents
In assets/build/blocks/Contributors/render.php around lines 11-12 and 395-396,
the render function call (echo render_wedocs_contributors_block(...)) is placed
inside the function_exists() guard so it only runs when the function is being
defined; move the echo call out of the guard so the guard only wraps the
function definition. Specifically, keep the if ( !
function_exists('render_wedocs_contributors_block') ) { function ... } block
as-is, then after the closing brace call echo
render_wedocs_contributors_block($attributes, $content, $block) so the function
is defined conditionally but always invoked.

Comment on lines +120 to +132
case 'all':
default:
// Get all contributors who have edited the post
$author_id = get_post_field('wedocs_contributors', $post->ID);
$authors = array_values($author_id); // return auhtors id.
foreach($authors as $author){
$contributors[]= get_userdata($author);
}


if ($author_id && ($author_user = get_userdata($author_id))) {
$contributors[] = $author_user;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Logic bug: Author may be added twice in 'all' mode.

The code iterates over $authors adding each contributor, then adds the author again at lines 130-132. This can result in duplicate entries.

🔎 Proposed fix
             case 'all':
             default:
                 // Get all contributors who have edited the post
                 $author_id = get_post_field('wedocs_contributors', $post->ID);
-                $authors = array_values($author_id); // return auhtors id.
-                foreach($authors as $author){
-                    $contributors[]= get_userdata($author);
-                }
-
-
-                if ($author_id && ($author_user = get_userdata($author_id))) {
-                    $contributors[] = $author_user;
+                if (is_array($author_id)) {
+                    foreach ($author_id as $author) {
+                        $user = get_userdata($author);
+                        if ($user) {
+                            $contributors[] = $user;
+                        }
+                    }
+                } elseif ($author_id && ($author_user = get_userdata($author_id))) {
+                    $contributors[] = $author_user;
                 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
case 'all':
default:
// Get all contributors who have edited the post
$author_id = get_post_field('wedocs_contributors', $post->ID);
$authors = array_values($author_id); // return auhtors id.
foreach($authors as $author){
$contributors[]= get_userdata($author);
}
if ($author_id && ($author_user = get_userdata($author_id))) {
$contributors[] = $author_user;
}
case 'all':
default:
// Get all contributors who have edited the post
$author_id = get_post_field('wedocs_contributors', $post->ID);
if (is_array($author_id)) {
foreach ($author_id as $author) {
$user = get_userdata($author);
if ($user) {
$contributors[] = $user;
}
}
} elseif ($author_id && ($author_user = get_userdata($author_id))) {
$contributors[] = $author_user;
}
🤖 Prompt for AI Agents
In assets/build/blocks/Contributors/render.php around lines 120 to 132, the code
appends contributors from $authors then unconditionally appends $author_user
again, causing duplicate entries; fix by removing the redundant append or
deduplicating before adding: either drop the final if-block that adds
$author_user (since it’s already added from $authors), or normalize $author_id
to an array and build $authors from it then ensure you only add each user once
(e.g., track added user IDs or filter duplicates with their IDs) before pushing
get_userdata results into $contributors.

Comment on lines +123 to +124
$author_id = get_post_field('wedocs_contributors', $post->ID);
$authors = array_values($author_id); // return auhtors id.
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Type safety: array_values() on potentially non-array value.

get_post_field('wedocs_contributors', $post->ID) may return a string, empty string, or WP_Error depending on the meta value. Calling array_values() on a non-array will cause a fatal error.

🔎 Proposed fix
-                $author_id = get_post_field('wedocs_contributors', $post->ID);
-                $authors = array_values($author_id); // return auhtors id.
+                $author_id = get_post_field('wedocs_contributors', $post->ID);
+                $authors = is_array($author_id) ? array_values($author_id) : [];
🤖 Prompt for AI Agents
In assets/build/blocks/Contributors/render.php around lines 123-124, the code
calls array_values() directly on the result of get_post_field which may be a
WP_Error, string, or empty value; update it to first guard against WP_Error,
then normalize the value to an array before calling array_values: if
is_wp_error($author_id) return/handle error (or set $authors = []), if
is_array($author_id) use array_values($author_id), if it's a non-empty scalar
wrap it as a single-element array (e.g. $authors = [$author_id]), otherwise set
$authors = []; this ensures type safety and avoids fatal errors.

Comment on lines +11 to +38
export {
generateBlockStyles,
generateTypographyStyles,
generateSpacingStyles,
generateElementStyles,
generateCustomProperties,
debounce,
isValidCSSValue,
convertToPx,
classNames,
getBreakpoints,
isBreakpoint
} from './block-helpers';

// Export default object with all helpers
export default {
generateBlockStyles,
generateTypographyStyles,
generateSpacingStyles,
generateElementStyles,
generateCustomProperties,
debounce,
isValidCSSValue,
convertToPx,
classNames,
getBreakpoints,
isBreakpoint
}; No newline at end of file
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Default export references identifiers that are not in scope.

The named re-exports on lines 11-22 make the functions available to consumers of this module, but they do not bring those identifiers into the local scope of this file. The default export object (lines 26-37) references generateBlockStyles, debounce, etc., which are undefined in this file's scope.

This will cause a ReferenceError at runtime when importing the default export.

🔎 Proposed fix
-// Export all helper functions
-export {
+// Import helpers for local use
+import {
 	generateBlockStyles,
 	generateTypographyStyles,
 	generateSpacingStyles,
 	generateElementStyles,
 	generateCustomProperties,
 	debounce,
 	isValidCSSValue,
 	convertToPx,
 	classNames,
 	getBreakpoints,
 	isBreakpoint
 } from './block-helpers';
+
+// Re-export all helper functions
+export {
+	generateBlockStyles,
+	generateTypographyStyles,
+	generateSpacingStyles,
+	generateElementStyles,
+	generateCustomProperties,
+	debounce,
+	isValidCSSValue,
+	convertToPx,
+	classNames,
+	getBreakpoints,
+	isBreakpoint
+};

 // Export default object with all helpers
 export default {
 	generateBlockStyles,

Committable suggestion skipped: line range outside the PR's diff.

🤖 Prompt for AI Agents
In src/blocks/helpers/index.js around lines 11-38, the file currently only
re-exports named helpers but then attempts to reference those identifiers for a
default export (causing ReferenceError); fix this by bringing the functions into
the local scope (either with a single import { generateBlockStyles,
generateTypographyStyles, generateSpacingStyles, generateElementStyles,
generateCustomProperties, debounce, isValidCSSValue, convertToPx, classNames,
getBreakpoints, isBreakpoint } from './block-helpers' or import * as helpers
from './block-helpers'), then re-export the named symbols and create the default
export object from those locally imported identifiers (or simply export default
helpers if using namespace import). Ensure the file both exports the named
symbols and exposes a valid default object referencing identifiers that exist in
this module scope.

Comment on lines +15 to +16
const Inspector = ({ attributes, setAttributes }) => {
return (
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Critical: Missing destructuring of attributes causes ReferenceError.

The component uses many attribute variables (tocTitle, supportedHeadings, showHierarchy, showNumbering, collapsibleOnMobile, smoothScroll, stickyMode, containerBackgroundColor, containerWidth, containerPadding, containerMargin, containerBorderStyle, containerBorderWidth, containerBorderColor, containerBorderRadius, titleColor, titleFontSize, titleFontWeight, listColor, listHoverColor, listFontSize) without destructuring them from attributes. This will cause a ReferenceError at runtime.

🔎 Proposed fix
 const Inspector = ({ attributes, setAttributes }) => {
+    const {
+        tocTitle,
+        supportedHeadings,
+        showHierarchy,
+        showNumbering,
+        collapsibleOnMobile,
+        smoothScroll,
+        stickyMode,
+        containerBackgroundColor,
+        containerWidth,
+        containerPadding,
+        containerMargin,
+        containerBorderStyle,
+        containerBorderWidth,
+        containerBorderColor,
+        containerBorderRadius,
+        titleColor,
+        titleFontSize,
+        titleFontWeight,
+        listColor,
+        listHoverColor,
+        listFontSize,
+    } = attributes;
+
     return (
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const Inspector = ({ attributes, setAttributes }) => {
return (
const Inspector = ({ attributes, setAttributes }) => {
const {
tocTitle,
supportedHeadings,
showHierarchy,
showNumbering,
collapsibleOnMobile,
smoothScroll,
stickyMode,
containerBackgroundColor,
containerWidth,
containerPadding,
containerMargin,
containerBorderStyle,
containerBorderWidth,
containerBorderColor,
containerBorderRadius,
titleColor,
titleFontSize,
titleFontWeight,
listColor,
listHoverColor,
listFontSize,
} = attributes;
return (
🤖 Prompt for AI Agents
In src/blocks/TableOfContents/Inspector.js around lines 15 to 16, the component
receives attributes but never destructures the individual props, causing
ReferenceError when variables like tocTitle, supportedHeadings, showHierarchy,
showNumbering, collapsibleOnMobile, smoothScroll, stickyMode,
containerBackgroundColor, containerWidth, containerPadding, containerMargin,
containerBorderStyle, containerBorderWidth, containerBorderColor,
containerBorderRadius, titleColor, titleFontSize, titleFontWeight, listColor,
listHoverColor, and listFontSize are referenced; fix by destructuring these
properties from the attributes parameter at the top of the component (e.g. const
{ tocTitle, supportedHeadings, ... } = attributes) so the component uses defined
variables, leaving setAttributes usage unchanged.

Comment on lines +109 to +152
// Get block attributes with proper defaults
$block_id = isset($attributes['blockId']) ? sanitize_text_field($attributes['blockId']) : 'toc-' . uniqid();
$toc_title = isset($attributes['tocTitle']) ? sanitize_text_field($attributes['tocTitle']) : 'Table of Contents';
$supported_headings = isset($attributes['supportedHeadings']) && is_array($attributes['supportedHeadings']) ? $attributes['supportedHeadings'] : ['h2', 'h3'];
$show_hierarchy = isset($attributes['showHierarchy']) ? (bool) $attributes['showHierarchy'] : true;
$show_numbering = isset($attributes['showNumbering']) ? (bool) $attributes['showNumbering'] : false;
$collapsible_on_mobile = isset($attributes['collapsibleOnMobile']) ? (bool) $attributes['collapsibleOnMobile'] : true;
$smooth_scroll = isset($attributes['smoothScroll']) ? (bool) $attributes['smoothScroll'] : true;
$sticky_mode = isset($attributes['stickyMode']) ? (bool) $attributes['stickyMode'] : false;
$additional_css_class = isset($attributes['additionalCssClass']) ? sanitize_text_field($attributes['additionalCssClass']) : '';

// Build CSS classes
$css_classes = ['wp-block-wedocs-table-of-contents'];
if (!empty($additional_css_class)) {
$css_classes[] = esc_attr($additional_css_class);
}
if ($sticky_mode) {
$css_classes[] = 'sticky-mode';
}
if ($collapsible_on_mobile) {
$css_classes[] = 'collapsible-mobile';
}
if ($smooth_scroll) {
$css_classes[] = 'smooth-scroll';
}

// Get block wrapper attributes
$wrapper_attributes = get_block_wrapper_attributes([
'class' => implode(' ', $css_classes),
'data-block-id' => esc_attr($block_id),
'data-supported-headings' => esc_attr(wp_json_encode($supported_headings)),
'data-show-hierarchy' => $show_hierarchy ? 'true' : 'false',
'data-show-numbering' => $show_numbering ? 'true' : 'false',
'data-smooth-scroll' => $smooth_scroll ? 'true' : 'false'
]);

// Apply inline styles
$inline_styles = '';
if (!empty($attributes['containerBackgroundColor'])) {
$inline_styles .= 'background-color: ' . esc_attr($attributes['containerBackgroundColor']) . ';';
}
if (!empty($attributes['containerWidth'])) {
$inline_styles .= 'width: ' . esc_attr($attributes['containerWidth']) . ';';
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Code executes at include time before $attributes is available.

Lines 109-152 run when the file is included, but $attributes isn't defined yet - it's only available when WordPress calls the render callback. This will cause PHP warnings/errors about undefined variables.

This code should either be inside the render callback or removed entirely as it duplicates logic already in render_wedocs_table_of_contents_block().

🤖 Prompt for AI Agents
In src/blocks/TableOfContents/render.php around lines 109-152, code is executing
at include time and references $attributes which is undefined until the
WordPress render callback runs; move this entire block into the
render_wedocs_table_of_contents_block() function (or delete it if it duplicates
that function) so it runs only when the render callback receives $attributes,
replace direct references to $attributes with the function's $attributes
parameter, and ensure any helper variables ($block_id, $css_classes,
$wrapper_attributes, $inline_styles, etc.) are computed inside the render
callback to avoid PHP notices and duplicate logic.

Comment on lines +375 to +438
/**
* Modern WordPress block render callback
* This function is automatically called by WordPress when the block.json has "render": "file:./render.php"
*/
// Extract attributes with defaults
$toc_title = $attributes['tocTitle'] ?? 'Table of Contents';
$supported_headings = $attributes['supportedHeadings'] ?? ['h2', 'h3'];
$show_hierarchy = $attributes['showHierarchy'] ?? true;
$show_numbering = $attributes['showNumbering'] ?? false;
$collapsible_on_mobile = $attributes['collapsibleOnMobile'] ?? true;
$container_background_color = $attributes['containerBackgroundColor'] ?? '';
$container_width = $attributes['containerWidth'] ?? '100%';
$container_padding = $attributes['containerPadding'] ?? ['top' => '20px', 'right' => '20px', 'bottom' => '20px', 'left' => '20px'];
$container_margin = $attributes['containerMargin'] ?? ['top' => '0px', 'right' => '0px', 'bottom' => '20px', 'left' => '0px'];
$container_border_style = $attributes['containerBorderStyle'] ?? 'solid';
$container_border_width = $attributes['containerBorderWidth'] ?? '1px';
$container_border_color = $attributes['containerBorderColor'] ?? '#e0e0e0';
$container_border_radius = $attributes['containerBorderRadius'] ?? '5px';
$title_color = $attributes['titleColor'] ?? '';
$title_font_size = $attributes['titleFontSize'] ?? '18px';
$title_font_weight = $attributes['titleFontWeight'] ?? '600';
$title_padding = $attributes['titlePadding'] ?? ['top' => '0px', 'right' => '0px', 'bottom' => '15px', 'left' => '0px'];
$list_color = $attributes['listColor'] ?? '';
$list_hover_color = $attributes['listHoverColor'] ?? '';
$list_font_size = $attributes['listFontSize'] ?? '14px';
$smooth_scroll = $attributes['smoothScroll'] ?? true;
$sticky_mode = $attributes['stickyMode'] ?? false;
$additional_css_class = $attributes['additionalCssClass'] ?? '';

// Build wrapper attributes
$wrapper_attributes = 'class="wp-block-wedocs-table-of-contents';
if ($collapsible_on_mobile) {
$wrapper_attributes .= ' toc-mobile-collapsible';
}
if ($sticky_mode) {
$wrapper_attributes .= ' toc-sticky';
}
if (!empty($additional_css_class)) {
$wrapper_attributes .= ' ' . esc_attr($additional_css_class);
}
$wrapper_attributes .= '"';

// Build inline styles
$inline_styles = '';
if (!empty($container_background_color)) {
$inline_styles .= 'background-color: ' . esc_attr($container_background_color) . '; ';
}
$inline_styles .= 'width: ' . esc_attr($container_width) . '; ';
$inline_styles .= 'padding: ' . esc_attr($container_padding['top']) . ' ' . esc_attr($container_padding['right']) . ' ' . esc_attr($container_padding['bottom']) . ' ' . esc_attr($container_padding['left']) . '; ';
$inline_styles .= 'margin: ' . esc_attr($container_margin['top']) . ' ' . esc_attr($container_margin['right']) . ' ' . esc_attr($container_margin['bottom']) . ' ' . esc_attr($container_margin['left']) . '; ';
$inline_styles .= 'border: ' . esc_attr($container_border_width) . ' ' . esc_attr($container_border_style) . ' ' . esc_attr($container_border_color) . '; ';
$inline_styles .= 'border-radius: ' . esc_attr($container_border_radius) . '; ';

$toc_content = wedocs_generate_toc_content_safe($supported_headings, $show_hierarchy, $show_numbering);

?>
<div <?php echo $wrapper_attributes; ?> <?php echo !empty($inline_styles) ? 'style="' . esc_attr($inline_styles) . '"' : ''; ?>>
<div class="toc-title" style="<?php echo !empty($title_color) ? 'color: ' . esc_attr($title_color) . '; ' : ''; ?>font-size: <?php echo esc_attr($title_font_size); ?>; font-weight: <?php echo esc_attr($title_font_weight); ?>; padding: <?php echo esc_attr($title_padding['top']) . ' ' . esc_attr($title_padding['right']) . ' ' . esc_attr($title_padding['bottom']) . ' ' . esc_attr($title_padding['left']); ?>;">
<?php echo esc_html($toc_title); ?>
</div>
<div class="toc-content" style="<?php echo !empty($list_color) ? 'color: ' . esc_attr($list_color) . '; ' : ''; ?>font-size: <?php echo esc_attr($list_font_size); ?>;">
<?php echo wp_kses_post($toc_content); ?>
</div>
</div>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Same issue: Duplicate rendering code outside of function.

This file has the identical problem as the build version - lines 375-438 contain rendering code outside of any function that will execute on every file include.

This appears to be the source file. The entire section from line 375 to end of file should be removed, as it duplicates render_wedocs_table_of_contents_block() defined above.

🤖 Prompt for AI Agents
In src/blocks/TableOfContents/render.php around lines 375 to 438 there is
duplicated block render code placed outside any function (it duplicates
render_wedocs_table_of_contents_block()), which causes it to run on every
include; remove the entire section from line 375 to the end of the file (the
duplicated rendering block) so only the previously defined
render_wedocs_table_of_contents_block() is used, and verify there are no
leftover stray PHP open/close tags or duplicated variable definitions after
removal.

Comment on lines +57 to +68
// Generate TOC HTML
const tocHTML = generateTOCHTML(headings, supportedHeadings, showHierarchy, showNumbering);
const tocContent = tocBlock.querySelector('.toc-content');
tocContent.innerHTML = tocHTML;

// Add IDs to headings if they don't have them
headings.forEach(function(heading, index) {
if (!heading.id) {
heading.id = 'toc-heading-' + index;
}
});
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

IDs are assigned to headings after TOC HTML is generated, causing broken anchor links.

The generateTOCHTML function (line 58) is called before IDs are assigned to headings (lines 63-67). When generateTOCHTML accesses heading.id on line 100, headings without existing IDs will have empty id values, and the fallback 'toc-heading-' + index won't match the IDs assigned later.

🔎 Proposed fix: Assign IDs before generating HTML
 	function generateTOC(tocBlock) {
 		const supportedHeadings = getSupportedHeadings(tocBlock);
 		const showHierarchy = tocBlock.dataset.showHierarchy !== 'false';
 		const showNumbering = tocBlock.dataset.showNumbering === 'true';

 		// Find all headings in the page content
 		const contentArea = document.querySelector('.entry-content, .post-content, main, .content') || document.body;
 		const headingSelector = supportedHeadings.map(h => h.toLowerCase()).join(', ');
 		const headings = contentArea.querySelectorAll(headingSelector);

 		if (headings.length === 0) {
 			const tocContent = tocBlock.querySelector('.toc-content');
 			tocContent.innerHTML = '<div class="toc-empty-state"><p>No headings found in the content.</p></div>';
 			return;
 		}

+		// Add IDs to headings BEFORE generating TOC HTML
+		headings.forEach(function(heading, index) {
+			if (!heading.id) {
+				heading.id = 'toc-heading-' + index;
+			}
+		});
+
 		// Generate TOC HTML
 		const tocHTML = generateTOCHTML(headings, supportedHeadings, showHierarchy, showNumbering);
 		const tocContent = tocBlock.querySelector('.toc-content');
 		tocContent.innerHTML = tocHTML;
-
-		// Add IDs to headings if they don't have them
-		headings.forEach(function(heading, index) {
-			if (!heading.id) {
-				heading.id = 'toc-heading-' + index;
-			}
-		});
 	}
🤖 Prompt for AI Agents
In src/blocks/TableOfContents/view.js around lines 57 to 68, IDs are being added
to headings after generateTOCHTML is called, so generateTOCHTML sees empty ids
and produces broken anchors; move the headings.forEach block that assigns ids to
run before calling generateTOCHTML (or alternatively update generateTOCHTML to
generate and use fallback ids itself), then call generateTOCHTML and set
tocContent.innerHTML so the TOC uses the correct, already-assigned ids.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants