=== Liuer Box ===
Contributors: liuer
Tags: custom fields, repeater, options page, meta box, custom meta
Requires at least: 6.0
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.0.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html

A custom fields framework with a visual builder and clean, native storage. Zero plugin dependencies.

== Description ==

Liuer Box lets you build custom fields for WordPress with a visual field-group builder, while keeping data stored cleanly in native post/term/user meta and options.

* **Visual builder** — create Field Groups, add fields, drag to reorder, choose where they appear. No code required.
* **Clean, native storage** — single fields are stored in one native meta row; complex fields (repeater / gallery / link) are stored as a single JSON row instead of many rows; global options are consolidated into a single `liuer_box_options` row. Your database stays small.
* **22 field types** — text, textarea, number, email, url, password, range, select, checkbox, radio, button group, true/false, WYSIWYG, image, gallery, file, oEmbed, color, link, date/time, **post object** (pick one or more posts of a chosen post type), and a nested **Repeater**, plus Tab and Message layout fields.
* **Locations** — Options Pages, Post types (meta boxes), Taxonomy terms, User profiles, and Page Templates.
* **Repeater with nesting** — drag-sort rows, collapse, min/max, dynamic row labels, repeaters inside repeaters.
* **Conditional logic** — show/hide a field based on another field's value, evaluated both client-side and server-side.
* **Field width & tabs** — lay fields out in columns and group them into tabs.
* **Multilingual ready** — per-post/term/user fields follow translations naturally; global option fields can use language-scoped values for Polylang/WPML, with Polylang string registration when available.
* **Developer friendly** — read values with `liuer_option()`, `liuer_field()`, `liuer_term()`, `liuer_user()`; write them with `liuer_update_field()`, `liuer_update_term()`, `liuer_update_user()`, `liuer_update_option()`; register groups in code with `liuer_box_register()`.

= Reading values in your theme =

The getters return RAW values (use them for logic, arrays, attachment IDs and HTML fields). Always escape on output:

`
$accent = liuer_option( 'accent' );                 // Options page value
$logo   = liuer_field( 'logo', null, $post_id );     // Post meta value (attachment ID)
$color  = liuer_term( 'color', $term_id );           // Term meta value
$phone  = liuer_user( 'phone', $user_id );           // User meta value

echo esc_html( liuer_field( 'subtitle' ) );
echo wp_get_attachment_image( liuer_field( 'logo' ), 'large' );

foreach ( (array) liuer_field( 'slides' ) as $row ) {
    echo esc_html( $row['title'] );
}
`

= Writing values from code =

Setters mirror the getters and store in the same native format (arrays become one JSON row). They store the value AS GIVEN, so sanitize your input first:

`
liuer_update_field( 'subtitle', sanitize_text_field( $text ), $post_id ); // post meta
liuer_update_field( 'logo', absint( $attachment_id ) );                    // current post
liuer_update_field( 'slides', array(                                       // array -> JSON row
    array( 'title' => 'One' ),
    array( 'title' => 'Two' ),
), $post_id );

liuer_update_term( 'color', '#025098', $term_id );   // term meta
liuer_update_user( 'phone', $phone, $user_id );      // user meta
liuer_update_option( 'accent', '#2271b1' );          // options page
`

= Safe output helpers (auto-escaping) =

Optional convenience helpers that echo already-escaped output, so you don't have to remember the right escaper:

`
liuer_e( 'subtitle' );            // echo esc_html() of a post field
liuer_attr_e( 'data_id' );        // echo esc_attr()
liuer_url_e( 'website' );         // echo esc_url()
liuer_img( 'logo', 'large' );     // echo a safe <img> from an attachment ID
liuer_wysiwyg( 'about' );         // echo with WordPress content filters

liuer_option_e( 'tagline' );      // same family for options
liuer_option_attr_e( 'accent' );
liuer_option_url_e( 'fanpage' );
liuer_option_img( 'logo', 'medium' );
`

== Installation ==

1. Upload the `liuer-box` folder to `/wp-content/plugins/`, or install the plugin through the Plugins screen.
2. Activate the plugin through the **Plugins** screen.
3. Go to **Liuer Box → Options Pages** to create an options page (optional), then **Liuer Box → Field Groups → Add Group** to build your fields and choose where they appear.

== Frequently Asked Questions ==

= Does it require any other plugin? =

No. Liuer Box has zero plugin dependencies. It only uses WordPress core APIs plus the bundled jQuery, wp.media and the WP color picker.

= Where is the data stored? =

Schema (field definitions) live in a single option. Field values are stored natively: single values as one post/term/user meta row; complex values (repeater, gallery, link) as a single JSON meta row; global options consolidated into one `liuer_box_options` row.

= Is it translation ready? =

Yes. Per-object fields follow the translation of their post/term/user. Global option fields can be marked "translatable" for Polylang/WPML language-scoped values, with Polylang string registration when available.

= What happens to my data when I delete the plugin? =

Data is intentionally preserved on uninstall so you don't lose content if you reinstall.

== Screenshots ==

1. The visual field group builder, with drag-sort, conditional logic and tabs.
2. An options page generated from a field group.
3. A repeater with nested sub-fields inside a post meta box.

== Changelog ==

= 1.0.0 =
* Initial release.

== Upgrade Notice ==

= 1.0.0 =
Initial release.
