Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes
Binary file added assets/images/gateways/common-sms.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
5 changes: 5 additions & 0 deletions includes/Admin/Menu.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,11 @@ public function render_page() {
public function enqueue_scripts() {
$asset_file = include TEXTY_DIR . '/dist/index.asset.php';

// The reusable `texty-components` bundle (window.texty.components) is
// registered globally by Texty\Assets so add-ons can depend on it on
// both admin and storefront. On this page it is pulled in on demand by
// whichever add-on script declares it as a dependency.

wp_register_script(
'texty-admin',
TEXTY_URL . '/dist/index.js',
Expand Down
83 changes: 83 additions & 0 deletions includes/Assets.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
<?php

namespace Texty;

defined( 'ABSPATH' ) || exit;

/**
* Shared asset registration.
*
* Registers the reusable components bundle (`window.texty.components`,
* handle `texty-components`) on wp-admin, the front-end, and the login page
* so add-ons that declare a `texty-components` dependency get it loaded on
* demand — including on storefront surfaces (checkout, my-account) and the
* wp-login.php registration form, where the admin SPA never loads. Nothing is
* enqueued here; consumers pull the bundle in by depending on the handle (or
* calling wp_enqueue_script directly).
*/
class Assets {

/**
* Wire the global registration on every request context an add-on may
* enqueue from: wp-admin, the front-end, and wp-login.php.
*/
public function __construct() {
add_action( 'admin_enqueue_scripts', [ $this, 'register_components' ], 5 );
add_action( 'wp_enqueue_scripts', [ $this, 'register_components' ], 5 );
add_action( 'login_enqueue_scripts', [ $this, 'register_components' ], 5 );
}

/**
* Register the `texty-components` handle.
*
* The bundle self-initializes `window.texty` (webpack library
* `['texty','components']`). In wp-admin the SPA localizes `var texty =
* {…}` onto that global, which would clobber `.components` unless the
* bundle loads *after* it — so `texty-admin` is added as a dependency
* there. On the front-end there is no localize step and the admin SPA is
* absent, so the base asset deps are used as-is.
*
* @return void
*/
public function register_components() {
if ( wp_script_is( 'texty-components', 'registered' ) ) {
return;
}

$asset_path = TEXTY_DIR . '/dist/components.asset.php';

if ( ! file_exists( $asset_path ) ) {
return;
}

$asset = include $asset_path;
$deps = isset( $asset['dependencies'] ) && is_array( $asset['dependencies'] ) ? $asset['dependencies'] : [];

if ( is_admin() ) {
$deps = array_merge( $deps, [ 'texty-admin' ] );
}

wp_register_script(
'texty-components',
TEXTY_URL . '/dist/components.js',
$deps,
isset( $asset['version'] ) ? $asset['version'] : TEXTY_VERSION,
true
);

// Base stylesheet for component-level styles (e.g. PhoneField's
// react-phone-input-2 layout). Emitted by the components entry as
// dist/style-components.css. Add-ons pull it by depending on this
// handle; nothing enqueues it here.
$style_path = TEXTY_DIR . '/dist/style-components.css';

if ( file_exists( $style_path ) && ! wp_style_is( 'texty-components', 'registered' ) ) {
wp_register_style(
'texty-components',
TEXTY_URL . '/dist/style-components.css',
[],
isset( $asset['version'] ) ? $asset['version'] : TEXTY_VERSION
);
}
}
}
2 changes: 1 addition & 1 deletion includes/Gateways/Clickatell.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function description() {
* @return string
*/
public function logo() {
return TEXTY_URL . '/assets/images/clickatell-logo.png';
return TEXTY_URL . '/assets/images/gateways/clickatell-logo.png';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion includes/Gateways/Fake.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ public function description() {
* @return string
*/
public function logo() {
return TEXTY_URL . '/assets/images/logo.svg';
return TEXTY_URL . '/assets/images/gateways/common-sms.png';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion includes/Gateways/Plivo.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function description() {
* @return string
*/
public function logo() {
return TEXTY_URL . '/assets/images/plivo-logo.png';
return TEXTY_URL . '/assets/images/gateways/plivo-logo.png';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion includes/Gateways/Twilio.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ public function description() {
* @return string
*/
public function logo() {
return TEXTY_URL . '/assets/images/twilio-logo.png';
return TEXTY_URL . '/assets/images/gateways/twilio-logo.png';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion includes/Gateways/Vonage.php
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public function name() {
* @return string
*/
public function logo() {
return TEXTY_URL . '/assets/images/vonage-logo.png';
return TEXTY_URL . '/assets/images/gateways/vonage-logo.png';
}

/**
Expand Down
2 changes: 1 addition & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 6 additions & 6 deletions src/components/PhoneField.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ const PhoneField = ({ element, onChange }: FieldComponentProps) => {
// react-phone-input-2 emits digits without the leading "+"; re-add it so the
// stored number stays E.164 (Twilio & co. require it for the From number).
const handleChange = (val: string): void => {
if (element.id) onChange(element.id, val ? `+${val.replace(/^\+/, '')}` : '');
if (element.id)
onChange(element.id, val ? `+${val.replace(/^\+/, '')}` : '');
};

return (
Expand All @@ -35,16 +36,15 @@ const PhoneField = ({ element, onChange }: FieldComponentProps) => {

<div className="w-full">
<PhoneInput
country="bd"
enableSearch
value={value}
onChange={handleChange}
enableSearch
disabled={element.disabled}
inputProps={{ id: element.id, name: element.id }}
containerClass="texty-phone-input"
inputClass="!h-9 !w-full !rounded-md !border !border-input !bg-background !pl-14 !text-sm !text-foreground"
buttonClass="!rounded-l-md !border-r !border-input !bg-background"
dropdownClass="!text-sm"
inputClass="h-9 w-full rounded-md border border-input bg-background pl-14 text-sm text-foreground"
buttonClass="rounded-l-md border-r border-input bg-background"
dropdownClass="text-sm"
/>
{element.description && (
<div className="mt-1.5 text-xs leading-relaxed text-muted-foreground">
Expand Down
22 changes: 22 additions & 0 deletions src/components/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
/**
* Public component surface for add-ons.
*
* Built as the `components` webpack entry (library `textyComponents`, handle
* `texty-components`) and consumed by add-ons via `import { … } from
* '@texty/components'`, which webpack externalizes to the shared global.
*
* PhoneField wraps react-phone-input-2; its base stylesheet is imported here
* so the components entry emits its own `dist/components.css`. Add-ons that use
* PhoneField on storefront surfaces (where the admin SPA sheet never loads)
* pull it in by depending on the `texty-components` style handle.
*
* The `?texty-components` resource query is load-bearing: the admin `index.tsx`
* imports the same `react-phone-input-2/lib/style.css`, and without a distinct
* request webpack would extract the single shared module into `style-index.css`
* (leaving no components sheet). The query makes this a distinct module so the
* components entry gets its own extracted stylesheet.
*/
import 'react-phone-input-2/lib/style.css?texty-components';

export { default as NotificationGroupSettings } from '../pages/notifications/components/NotificationGroupSettings';
export { default as PhoneField } from './PhoneField';
Loading
Loading