Initial commit: WordPress wp-content (themes, plugins, languages)

- Theme: momentry (custom theme with REST API routes)
- Plugins: code-snippets (contains all API proxies)
- Languages: zh_TW translations
- Excludes: cache, backups, uploads, logs
This commit is contained in:
OpenCode
2026-05-29 19:07:56 +08:00
commit 09ef1f000f
6521 changed files with 867163 additions and 0 deletions

View File

@@ -0,0 +1,27 @@
import React from 'react'
import classnames from 'classnames'
import type { ReactNode } from 'react'
import type { SnippetType } from '../../types/Snippet'
export type BadgeName = SnippetType | 'core' | 'pro' | 'ai' | 'cloud' | 'bundles' | 'cloud_search' | 'beta'
const badgeIcons: Partial<Record<BadgeName, string>> = {
cond: 'randomize',
cloud: 'cloud',
bundles: 'screenoptions',
cloud_search: 'search'
}
export interface BadgeProps {
name: BadgeName
small?: boolean
inverted?: boolean
children?: ReactNode
}
export const Badge: React.FC<BadgeProps> = ({ name, small, inverted, children }) =>
<span className={classnames('badge', `${name}-badge`, { 'small-badge': small, 'inverted-badge': inverted })}>
{badgeIcons[name]
? <span className={`dashicons dashicons-${badgeIcons[name]}`} />
: children ?? name}
</span>

View File

@@ -0,0 +1,49 @@
import React from 'react'
import classnames from 'classnames'
import type { ButtonHTMLAttributes } from 'react'
export interface ButtonProps extends Omit<ButtonHTMLAttributes<HTMLButtonElement>, 'id' | 'name'> {
id?: string
name?: string
primary?: boolean
secondary?: boolean
small?: boolean
large?: boolean
link?: boolean
}
export const Button: React.FC<ButtonProps> = ({
id,
children,
className,
name,
primary = false,
secondary = false,
small = false,
large = false,
link = false,
type = 'button',
onClick,
...props
}) =>
<button
id={id ?? name}
name={name}
type={type}
{...props}
onClick={event => {
if (onClick) {
event.preventDefault()
onClick(event)
}
}}
className={classnames('button', className, {
'button-primary': primary,
'button-secondary': secondary,
'button-large': large,
'button-small': small,
'button-link': link
})}
>
{children}
</button>

View File

@@ -0,0 +1,49 @@
import React from 'react'
import { __ } from '@wordpress/i18n'
import { Button, Flex, Modal } from '@wordpress/components'
import type { ReactNode } from 'react'
export interface ConfirmDialogProps {
open?: boolean
title: string
onConfirm?: VoidFunction
onCancel: VoidFunction
confirmLabel?: string
cancelLabel?: string
children?: ReactNode,
confirmButtonClassName?: string
}
export const ConfirmDialog: React.FC<ConfirmDialogProps> = ({
open,
title,
onConfirm,
onCancel,
children,
confirmLabel = __('OK', 'code-snippets'),
cancelLabel = __('Cancel', 'code-snippets'),
confirmButtonClassName
}) =>
open
? <Modal
title={title}
onRequestClose={onCancel}
closeButtonLabel={cancelLabel}
isDismissible={true}
onKeyDown={event => {
if ('Enter' === event.key) {
onConfirm?.()
}
}}
>
{children}
<Flex direction="row" justify="flex-end">
<Button variant="tertiary" onClick={onCancel}>
{cancelLabel}
</Button>
<Button variant="primary" onClick={onConfirm} className={confirmButtonClassName}>
{confirmLabel}
</Button>
</Flex>
</Modal>
: null

View File

@@ -0,0 +1,71 @@
import { Spinner } from '@wordpress/components'
import { __ } from '@wordpress/i18n'
import React, { useState } from 'react'
import { Button } from './Button'
import { CopyIcon } from './icons/CopyIcon'
import type { ButtonProps } from './Button'
const TIMEOUT = 1500
enum Status {
INITIAL,
PROGRESSING,
SUCCESS,
ERROR
}
interface StatusIconProps {
status: Status
}
const StatusIcon: React.FC<StatusIconProps> = ({ status }) => {
switch (status) {
case Status.INITIAL:
return <CopyIcon />
case Status.PROGRESSING:
return <span className="spinner-wrapper"><Spinner /></span>
case Status.SUCCESS:
return <span className="dashicons dashicons-yes"></span>
case Status.ERROR:
return <span className="dashicons dashicons-warning"></span>
}
}
export interface CopyToClipboardButtonProps extends ButtonProps {
text: string
timeout?: number
}
export const CopyToClipboardButton: React.FC<CopyToClipboardButtonProps> = ({
text,
timeout = TIMEOUT,
...props
}) => {
const [status, setStatus] = useState(Status.INITIAL)
const clipboard = window.navigator.clipboard as Clipboard | undefined
const handleClick = () => {
setStatus(Status.PROGRESSING)
clipboard?.writeText(text)
.then(() => {
setStatus(Status.SUCCESS)
setTimeout(() => setStatus(Status.INITIAL), timeout)
})
.catch((error: unknown) => {
console.error('Failed to copy text to clipboard.', error)
setStatus(Status.ERROR)
})
}
return clipboard && window.isSecureContext
? <Button
className="code-snippets-copy-text"
onClick={handleClick}
{...props}
>
<StatusIcon status={status} />
{__('Copy', 'code-snippets')}
</Button>
: null
}

View File

@@ -0,0 +1,22 @@
import { __ } from '@wordpress/i18n'
import classnames from 'classnames'
import React from 'react'
import type { ReactNode } from 'react'
export interface DismissibleNoticeProps {
className?: classnames.Argument
onDismiss: VoidFunction
children?: ReactNode
}
export const DismissibleNotice: React.FC<DismissibleNoticeProps> = ({ className, onDismiss, children }) =>
<div id="message" className={classnames('notice fade is-dismissible', className)}>
<>{children}</>
<button type="button" className="notice-dismiss" onClick={event => {
event.preventDefault()
onDismiss()
}}>
<span className="screen-reader-text">{__('Dismiss notice.', 'code-snippets')}</span>
</button>
</div>

View File

@@ -0,0 +1,46 @@
import React from 'react'
import classnames from 'classnames'
import { __ } from '@wordpress/i18n'
import type { InputHTMLAttributes } from 'react'
export interface SubmitButtonProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'id' | 'name' | 'value'> {
id?: string
name?: string
primary?: boolean
small?: boolean
large?: boolean
wrap?: boolean
text?: string
}
export const SubmitButton: React.FC<SubmitButtonProps> = ({
id,
text,
name = 'submit',
primary,
small,
large,
wrap,
className,
...inputProps
}) => {
const button =
<input
id={id ?? name}
type="submit"
name={name}
value={text ?? __('Save Changes', 'code-snippets')}
className={classnames(
'button',
{
'button-primary': primary,
'button-small': small,
'button-large': large
},
className
)}
{...inputProps}
/>
return wrap ? <p className="submit">{button}</p> : button
}

View File

@@ -0,0 +1,25 @@
import React from 'react'
import classnames from 'classnames'
import type { ReactNode } from 'react'
export interface TooltipProps {
block?: boolean
inline?: boolean
start?: boolean
end?: boolean
icon?: ReactNode
children: ReactNode
className?: classnames.Argument
}
export const Tooltip: React.FC<TooltipProps> = ({ block, inline, start, end, icon, className, children }) =>
<div className={classnames(
'tooltip',
{ 'tooltip-block': block, 'tooltip-inline': inline, 'tooltip-start': start, 'tooltip-end': end },
className
)}>
{icon ?? <span className="dashicons dashicons-editor-help"></span>}
<div className="tooltip-content">
{children}
</div>
</div>

View File

@@ -0,0 +1,37 @@
import { ExternalLink } from '@wordpress/components'
import { createInterpolateElement } from '@wordpress/element'
import { __ } from '@wordpress/i18n'
import React, { useState } from 'react'
import { isLicensed } from '../../utils/screen'
import { Button } from './Button'
export const UpsellBanner = () => {
const [isDismissed, setIsDismissed] = useState(false)
return isDismissed || isLicensed() || window.CODE_SNIPPETS_EDIT?.hideUpsell
? null
: <div className="code-snippets-upsell-banner">
<img
src={`${window.CODE_SNIPPETS?.urls.plugin}/assets/icon.svg`}
alt={__('Code Snippets logo', 'code-snippets')}
height="34"
/>
<p>
{createInterpolateElement(
__('Unlock <strong>cloud sync, snippet conditions, AI features</strong> and much more with Code Snippets Pro.', 'code-snippets'),
{ strong: <strong /> }
)}
</p>
<ExternalLink
className="button button-primary button-large"
href="https://codesnippets.pro/pricing/"
>
{__('Get Started', 'code-snippets')}
</ExternalLink>
<Button small link onClick={() => setIsDismissed(true)}>
<span className="dashicons dashicons-no-alt"></span>
</Button>
</div>
}

View File

@@ -0,0 +1,62 @@
import { createInterpolateElement } from '@wordpress/element'
import React from 'react'
import { __ } from '@wordpress/i18n'
import { Modal } from '@wordpress/components'
import type { Dispatch, SetStateAction } from 'react'
export interface UpsellDialogProps {
isOpen: boolean
setIsOpen: Dispatch<SetStateAction<boolean>>
}
export const UpsellDialog: React.FC<UpsellDialogProps> = ({ isOpen, setIsOpen }) =>
isOpen
? <Modal
title=""
className="code-snippets-upsell-dialog"
onRequestClose={() => {
setIsOpen(false)
}}
>
<img
src={`${window.CODE_SNIPPETS?.urls.plugin}/assets/icon.svg`}
alt={__('Code Snippets logo', 'code-snippets')}
/>
<h1>
{createInterpolateElement(
__('Unlock all cloud sync features and many more, with <span>Code Snippets Pro</span>', 'code-snippets'),
{ span: <span /> }
)}
</h1>
<p>
{createInterpolateElement(
__('With Code Snippets Pro you can connect your WordPress sites to the code snippets cloud platform and be able to <strong>backup, synchronise, collaborate, and deploy</strong> your snippets from one central location.', 'code-snippets'),
{ strong: <strong /> }
)}
</p>
<a
href="https://codesnippets.pro/pricing/"
className="button button-primary button-large"
rel="noreferrer" target="_blank"
>
{__('Explore Code Snippets Pro', 'code-snippets')}
</a>
<h2>{__("Here's what else you get with Pro:", 'code-snippets')}</h2>
<ul>
<li>{__('Create, explain and verify snippets with AI', 'code-snippets')}</li>
<li>{__('Control when snippets run with Conditions', 'code-snippets')}</li>
<li>{__('CSS stylesheet snippets', 'code-snippets')}</li>
<li>{__('Minified JavaScript snippets', 'code-snippets')}</li>
<li>{__('Editor blocks and Elementor widgets', 'code-snippets')}</li>
<li>{__('Cloud sync and backup', 'code-snippets')}</li>
<li>{__('Cloud share and deploy', 'code-snippets')}</li>
<li>{__('Cloud bundles and teams', 'code-snippets')}</li>
<li>{__('WP-CLI commands', 'code-snippets')}</li>
<li>{__('And much more!', 'code-snippets')}</li>
</ul>
</Modal>
: null

View File

@@ -0,0 +1,12 @@
import React from 'react'
export const CopyIcon = () =>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d="M12 6V4.5C12 4.10218 11.842 3.72064 11.5607 3.43934C11.2794 3.15804 10.8978 3 10.5 3H4.5C4.10218 3 3.72064 3.15804 3.43934 3.43934C3.15804 3.72064 3 4.10218 3 4.5V10.5C3 10.8978 3.15804 11.2794 3.43934 11.5607C3.72064 11.842 4.10218 12 4.5 12H6M6 7.5C6 7.10218 6.15804 6.72065 6.43934 6.43934C6.72065 6.15804 7.10218 6 7.5 6H13.5C13.8978 6 14.2794 6.15804 14.5607 6.43934C14.842 6.72065 15 7.10218 15 7.5V13.5C15 13.8978 14.842 14.2794 14.5607 14.5607C14.2794 14.842 13.8978 15 13.5 15H7.5C7.10218 15 6.72065 14.842 6.43934 14.5607C6.15804 14.2794 6 13.8978 6 13.5V7.5Z"
stroke="#F0F0F0"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>

View File

@@ -0,0 +1,20 @@
import React from 'react'
export const ExpandIcon = () =>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 3H15V6" />
<path d="M10.5 7.5L15 3L10.5 7.5Z" />
<path d="M6 15H3V12" />
<path d="M3 15L7.5 10.5L3 15Z" />
<path d="M12 15H15V12" />
<path d="M10.5 10.5L15 15L10.5 10.5Z" />
<path d="M6 3H3V6" />
<path d="M3 3L7.5 7.5L3 3Z" />
<path
d="M12 3H15M15 3V6M15 3L10.5 7.5M6 15H3M3 15V12M3 15L7.5 10.5M12 15H15M15 15V12M15 15L10.5 10.5M6 3H3M3 3V6M3 3L7.5 7.5"
stroke="currentcolor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>

View File

@@ -0,0 +1,20 @@
import React from 'react'
export const MinimiseIcon = () =>
<svg width="18" height="18" viewBox="0 0 18 18" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M3.75 6.75H6.75V3.75" />
<path d="M2.25 2.25L6.75 6.75L2.25 2.25Z" />
<path d="M3.75 11.25H6.75V14.25" />
<path d="M2.25 15.75L6.75 11.25L2.25 15.75Z" />
<path d="M14.25 6.75H11.25V3.75" />
<path d="M11.25 6.75L15.75 2.25L11.25 6.75Z" />
<path d="M14.25 11.25H11.25V14.25" />
<path d="M11.25 11.25L15.75 15.75L11.25 11.25Z" />
<path
d="M3.75 6.75H6.75M6.75 6.75V3.75M6.75 6.75L2.25 2.25M3.75 11.25H6.75M6.75 11.25V14.25M6.75 11.25L2.25 15.75M14.25 6.75H11.25M11.25 6.75V3.75M11.25 6.75L15.75 2.25M14.25 11.25H11.25M11.25 11.25V14.25M11.25 11.25L15.75 15.75"
stroke="currentcolor"
strokeWidth="1.5"
strokeLinecap="round"
strokeLinejoin="round"
/>
</svg>