npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@taktdev/components

v1.1.0-beta.22

Published

WordPress Gutenberg components to be used on themes

Downloads

1,065

Readme

Takt WordPress Components

A collection of reusable React components for building custom Gutenberg authoring experiences as part of Takt's WordPress ensemble. These components are designed to streamline editor development and provide advanced UI features for block and panel creation.

Components Overview

Below is a brief description of each component included in this package:

AdvancedRichText

An enhanced RichText component for Gutenberg blocks, supporting custom formatting, tag filtering, and optional line break disabling.

Props:

  • value (required): string
  • onChange (required): function
  • allowedFormats (optional): string[]
  • disableLineBreaks (optional): boolean
  • ...all RichText Props from @wordpress/block-editor

Appender

A wrapper for the default Gutenberg block appender, allowing for custom styling and positioning when adding new blocks.

Props:

  • className (optional): string
  • clientId (optional): string
  • style (optional): object

BaseButton

Thin wrapper over BaseLink with button-style defaults. Exposes a variation prop (default 'primary') and, by default, shows a variation toggle in the popover that the theme can override or disable.

BaseButton is for composition: themes wrap it with their own component (e.g. ThemeButton) that injects styling classes based on the variation. The component itself ships zero styling.

Props: all BaseLink props except children, allowedFormats, and variations, plus:

  • variation (optional): 'primary' | 'secondary' | 'tertiary' | string — variation key (default 'primary')
  • variations (optional): BaseLinkVariations{ options: { value: string; label: string }[]; value: string; label?: string }. Overrides the default primary/secondary/tertiary set
  • allowVariationChange (optional): boolean — show the variation toggle in the popover (default true)

Exported types: BaseButtonProps, BaseButtonVariationTypes, BaseButtonVariations

BaseHeading

A structural section-heading assembly: eyebrow + heading + description + buttons. Ships zero styling — each slot accepts a *ClassName prop so a theme wrapper can inject its own classes. Mirrors the PHP BaseHeading renderer for editor/front-end parity.

Props:

Content

  • eyebrow (optional): string
  • heading (optional): string
  • description (optional): string
  • buttons (optional): BaseHeadingButton[]LinkData & { variation?: string }

Structure

  • headingTag (optional): 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' (default 'h2')
  • headingId (optional): string — id on the heading element (for in-page anchors)

Toggles

  • enableEyebrow / enableHeading / enableDescription / enableButtons (optional): boolean (default true)

Description mode

  • longFormDescription (optional): boolean (default false) — when true, renders the description with LongFormRichText (paragraphs, inline headings, lists). When false, renders with AdvancedRichText (single paragraph with inline formatting).

ClassName slots

  • className, topGroupClassName, eyebrowClassName, headingClassName, bottomGroupClassName, descriptionClassName, buttonsClassName
  • buttonClassName (optional): (button: BaseHeadingButton, index: number) => string — per-button class resolver

Button config

  • buttonVariations (optional): string[] — ordered variations (default ['primary', 'secondary', 'tertiary'])

  • resolveButtonDefaults (optional): (button: BaseHeadingButton, index: number) => Partial<BaseHeadingButton> — compute index-dependent defaults for a button. Returned keys fall back into the button when it lacks an explicit value, and are frozen onto the button data at reorder time so anything defaulted-by-index (variation, accent, icon side, …) follows the button to its new position instead of staying pinned to the old one. The built-in variation default from buttonVariations is always applied; values returned here override it and add any other per-index defaults the theme needs. Use this instead of resolving index-dependent fields at render time inside your buttonComponent — otherwise a reorder will leave those fields behind.

  • buttonComponent (optional): BaseHeadingButtonComponent — substitute component for the per-button render call. Defaults to BaseButton. Lets themes render every button inside a heading through their own ThemeButton wrapper without reimplementing BaseHeading. The component must forward its onChange prop, otherwise buttons will appear read-only when rendered inside BaseHeading.

    <BaseHeading
      buttons={[ /* ... */ ]}
      buttonComponent={ThemeButton}
    />

Placeholders

  • eyebrowPlaceholder, headingPlaceholder, descriptionPlaceholder, buttonPlaceholder (optional): string

Plus onChange and all <div> HTML attributes except onChange.

Exported types: BaseHeadingProps, BaseHeadingButton, BaseHeadingButtonComponent

BaseLink

Foundational link component designed for theme composition. Renders an <a> with post/taxonomy URL resolution, new-tab handling, and a popover editor with extensible slots. Unlike the older Link component, BaseLink supports custom popover content via popoverBefore / popoverAfter, a configurable variations picker, and any standard anchor HTML attribute via prop spread.

Use BaseLink (and the BaseButton / BaseHeading built on it) when building theme-level wrappers. Keep Link / Button for their existing call sites.

Props:

  • link (optional): { title, url, postId?, postType?, opensInNewTab?, label? }
  • onChange (optional): (payload) => void
  • children (optional): ReactNode
  • before (optional): ReactNode
  • after (optional): ReactNode
  • tagName (optional): string (default 'span') — tag for the title element
  • allowedFormats (optional): string[] — inline formats allowed in the title (default [])
  • placeholder (optional): string
  • className (optional): string — class on the <a>
  • titleClassName (optional): string — class on the title element
  • anchor (optional): HTMLElement — popover anchor override
  • openPopupOnClick (optional): boolean (default true)
  • popupVisible (optional): boolean — controlled popover visibility
  • showTitleInPopover (optional): boolean — expose a title field inside the popover
  • focusOnMount (optional): string | boolean
  • validateLink (optional): boolean — verify post/term exists and is published
  • autoUpdateLink (optional): boolean — refresh the stored URL from the post if it changed
  • popoverBefore (optional): ReactNode — custom content above the LinkControl
  • popoverAfter (optional): ReactNode — custom content below the LinkControl
  • variations (optional): BaseLinkVariations{ options: { value: string; label: string }[]; value: string; label?: string }. Shows a variation toggle in the popover.

Plus all <a> HTML attributes (via AnchorHTMLAttributes) except onChange.

DOM hooks: the rendered <a> carries data-empty="" when the link has no url and no postId. Themes can use [data-empty] to style unconfigured buttons — e.g. dim a trailing arrow glyph to signal that the link is still empty. The attribute is omitted once either url or postId is set. Because BaseButton wraps BaseLink, the same hook is available there.

Exported types: BaseLinkProps, BaseLinkVariations, BaseLinkChangePayload

LinkEditor

The controlled, container-agnostic body of the link-editing popover used internally by Link, BaseLink, and Button: the LinkControl URL search, "open in new tab" toggle, aria-label field, and an optional variation picker. It renders no Popover and no anchor, so you can drop it into your own Popover, an InspectorControls panel, or any custom container — reusing the link-editing UI without the anchor/popover machinery.

Props:

  • value (required): LinkValue{ title, url, postId?, postType?, opensInNewTab?, label? }
  • onChange (required): (value: LinkChangePayload) => void
  • showTitle (optional): boolean (default false) — show LinkControl's title field; also drives the title-sync rule applied to incoming changes
  • syncTitle (optional): boolean — force-enable/disable adopting the control's title regardless of showTitle (e.g. Button passes false so the inline title is never overwritten by the popover)
  • variations (optional): LinkEditorVariations{ options: { value: string; label: string }[]; value: string; label?: string }
  • before / after (optional): ReactNode — slots rendered before/after the standard field stack

Exported types: LinkEditorProps, LinkEditorVariations

Usage (InspectorControls):

import { LinkEditor } from "@taktdev/components";
import { InspectorControls } from "@wordpress/block-editor";
import { PanelBody } from "@wordpress/components";

<InspectorControls>
  <PanelBody title="Link">
    <LinkEditor
      value={link}
      onChange={(next) => setAttributes({ link: { ...link, ...next } })}
      showTitle
    />
  </PanelBody>
</InspectorControls>

Button

A flexible button component with support for different variations (primary, secondary, tertiary), link integration, and advanced controls for editing button properties in the editor.

Props:

  • link (optional): { title, url, postId?, postType?, opensInNewTab?, label? }
  • className (optional): string
  • onChange (optional): function
  • placeholder (optional): string
  • focusOnMount (optional): string | boolean
  • variation (optional): 'primary' | 'secondary' | 'tertiary'
  • allowVariationChange (optional): boolean
  • before (optional): ReactNode
  • after (optional): ReactNode
  • validateLink (optional): boolean
  • autoUpdateLink (optional): boolean
  • mergeRef (optional): boolean
  • ...all anchor element attributes except onChange

FilteredServerSideRender

A server-side render component with additional filtering and query options, useful for rendering dynamic block previews with custom query selectors and attributes.

Props:

  • block (optional): string
  • attributes (optional): object
  • urlQueryArgs (optional): object
  • httpMethod (optional): 'GET' | 'POST'
  • url (optional): string
  • EmptyResponsePlaceholder (optional): React.ComponentType | null
  • LoadingResponsePlaceholder (optional): React.ComponentType | null
  • querySelector (optional): string
  • clientId (optional): string
  • className (optional): string
  • serverSideRenderRef (optional): any
  • preventInteraction (optional): boolean

ImageDropUploader

A drag-and-drop image uploader for Gutenberg, supporting image selection, upload, and focal point editing.

Props:

  • image (optional): ImageProps | number
  • onSelect (optional): function
  • allowedTypes (optional): string[]
  • className (optional): string
  • imageClassName (optional): string
  • imageStyle (optional): object
  • placeholderClassName (optional): string

IconPicker

A toolbar-based icon picker for Gutenberg blocks, supporting both suggested (predefined) icons and custom icons from the WordPress media library. Renders the selected icon inline where the component is placed.

Props:

  • value (optional): { slug?: string; mediaId?: number }
  • onChange (required): (value: IconPickerValue | null) => void
  • suggestedIcons (optional): SuggestedIcon[] — array of { name: string; label: string; icon: React.FC<React.SVGProps<SVGSVGElement>> }
  • iconSize (optional): number (default: 48) — size of icons in the popover grid
  • ...all <span> attributes except onChange (applied to the icon wrapper)

Exported Types:

  • SuggestedIcon{ name: string; label: string; icon: React.FC<React.SVGProps<SVGSVGElement>> }
  • IconPickerValue{ slug?: string; mediaId?: number }
  • IconPickerProps

Usage:

import { IconPicker, SuggestedIcon } from "@taktdev/components";
import { ReactComponent as IconYoutube } from "./resources/icon-youtube.svg";

const suggestedIcons: SuggestedIcon[] = [
  { name: "youtube", label: "YouTube", icon: IconYoutube },
];

<IconPicker
  value={iconSlug ? { slug: iconSlug } : mediaId ? { mediaId } : null}
  onChange={(icon) => setAttributes({
    iconSlug: icon?.slug ?? undefined,
    logoId: icon?.mediaId ?? undefined,
  })}
  suggestedIcons={suggestedIcons}
  iconSize={24}
/>

ImageOrInlineSvg

Displays an image by ID or attachment, with special handling for inline SVGs (fetches and injects SVG markup for SVG images).

Props:

  • imageId (optional): number
  • attachment (optional): Attachment
  • ...all standard <img> attributes

Link

A link component with advanced controls for editing link properties, including support for post links, new tab toggling, and custom labels.

Props:

  • children (optional): ReactNode
  • before (optional): ReactNode
  • after (optional): ReactNode
  • link (optional): { title, url, postId?, postType?, opensInNewTab?, label? }
  • className (optional): string
  • titleClassName (optional): string
  • onChange (optional): function
  • tagName (optional): string
  • allowedFormats (optional): []
  • placeholder (optional): string
  • anchor (optional): HTMLElement
  • focusOnMount (optional): string | boolean
  • validateLink (optional): boolean
  • autoUpdateLink (optional): boolean
  • openPopupOnClick (optional): boolean
  • popupVisible (optional): boolean
  • showPopupTitleField (optional): boolean

MediaUploadPanel

A media upload panel with optional focal point picker, designed for selecting and editing images or other media within block controls.

Props:

  • media (optional): ImageProps | number
  • label (optional): string
  • onSelect (optional): function
  • allowedTypes (optional): string[]
  • enableFocalPoint (optional): boolean

LongFormRichText

A multi-block rich-text editor that lets authors mix paragraphs, inline headings (h1–h6), and ordered/unordered lists inside a single HTML attribute. A toolbar dropdown switches block types, Enter creates new blocks, and Backspace merges them — similar to the block editor's own paragraph flow but scoped to one attribute.

Useful for description or body-copy fields where a single paragraph isn't enough, but a full InnerBlocks canvas would be too much ceremony.

Props:

  • value (required): string — serialized HTML
  • onChange (required): (html: string) => void
  • allowedBlocks (optional): LongFormBlockType[] — which block types the author can switch to. Default: ['paragraph', 'h3', 'h4', 'ul', 'ol']
  • allowedFormats (optional): string[] — inline formats allowed inside each block. Default: ['core/bold', 'core/italic', 'core/link']
  • className (optional): string
  • placeholder (optional): string

Exported types:

  • LongFormBlockType'paragraph' | 'h1' | ... | 'h6' | 'ul' | 'ol'

PopoverExternalLink

A popover input for external links, phone numbers, or emails, with protocol handling and inline editing UI.

Props:

  • children (optional): ReactNode
  • value (optional): string
  • onChange (optional): function
  • label (optional): string
  • placeholder (optional): string
  • className (optional): string
  • type (optional): 'link' | 'phone' | 'email'
  • includeProtocol (optional): boolean

PostSelectorSortable

A sortable post selector component for choosing and reordering posts of any type, with support for thumbnails and custom limits.

Props:

  • value (required): number[] | number
  • onChange (required): function
  • postTypes (optional): string[]
  • limit (optional): number | string
  • title (optional): string
  • onDocumentPanel (optional): boolean
  • forceReturnAsArray (optional): boolean
  • displayThumbnails (optional): boolean

TaxonomySelect

A taxonomy selector with multi-select and sorting, allowing users to pick and order taxonomy terms (categories, tags, etc.) in the editor.

Props:

  • title (optional): string
  • value (required): number[]
  • taxonomy (optional): string
  • onChange (optional): function
  • selectedFirst (optional): boolean
  • displaySearch (optional): boolean
  • limitHeight (optional): boolean
  • Hierarchical (optional): boolean

Hooks & helpers

Reusable pieces of the link-editing logic, extracted from Link / BaseLink / Button so custom link UIs (custom popovers, inspector panels) don't have to reimplement them.

useLinkField

Owns the WordPress-data side of a link field: resolves a postId / postType reference (post or taxonomy term) to its canonical URL and, optionally, validates and auto-corrects the stored URL against it.

Signature: useLinkField(link: LinkValue, options?) => { isValidLink: boolean }

Options:

  • validateLink (optional): boolean — report isValidLink: false when the referenced entity no longer resolves
  • autoUpdateLink (optional): boolean — emit onChange with the refreshed URL when the resolved permalink drifts from the stored one
  • onChange (optional): (value: LinkChangePayload) => void

mapLinkControlValue

Pure helper that maps a LinkControl onChange value back onto the LinkValue model — extracts the numeric postId / postType (only numeric ids are entity references) and applies the title-sync rule.

Signature: mapLinkControlValue(link: LinkValue, value, { showTitle?, syncTitle? }) => LinkChangePayload

useLinkPopover

Owns the popover open/close lifecycle shared by the anchor-rendering link components: visibility, popupVisible sync, inline-vs-toolbar trigger source, the anchor/popover refs, and an iframe-aware close (correct when focus moves across the editor-canvas iframe boundary).

Options: { popupVisible?: boolean; openPopupOnClick?: boolean }

Returns: { isVisible, setIsVisible, triggerSource, buttonRef, setPopoverNode, toolbarAnchor, setToolbarAnchor, closePopover, open, handleFocus, handleBlur, toggleFromToolbar } — wire buttonRef to the <a>, setPopoverNode to the Popover ref, and setToolbarAnchor to a toolbar button when offering a toolbar trigger.

Shared types:

  • LinkValue{ title: string; url: string; postId?: number | null; postType?: string | null; opensInNewTab?: boolean; label?: string }
  • LinkChangePayloadPartial<LinkValue> & { variation?: string }

For detailed usage and props, see the source code for each component in the src/ directory.