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 🙏

© 2024 – Pkg Stats / Ryan Hefner

apostrophe-palette

v2.0.30

Published

In-context style toggling save to the apostrophe-global doc

Downloads

70

Readme

CircleCI

apostrophe-palette

An in-context interface for changing CSS

apostrophe-palette demo

apostrophe-palette is a bundle that provides an in-context interface for changing the values of developer-set CSS properties. The values are stored in the apostrophe-global document and applied to the site whenever the stylesheet link is included in a template. Adjusting values via the palette interface renders changes to the site instantly.

Developers define properties that can be changed by passing the module an array of apostrophe-schema fields.

apostrophe-palette assumes you want access to this schema data everywhere (extends apostrophe-global).

The bundle includes:

  • apostrophe-palette-global pushes your palette schema to the apostrophe-global module
  • apostrophe-palette-schemas provides identifying wrappers for schema fields
  • apostrophe-palette-widgets provides the main interface for interacting with the schema and hooks for saving / reacting.
  • apostrophe-palette-admin-bar palette adds itself to a list of admin bar menu items to hide when apostrophe-workflow is in preview/live mode

Example configuration

modules: {
  // ... project level configuration
  'apostrophe-palette-admin-bar': {},
  'apostrophe-palette-widgets': {},
  'apostrophe-palette': {},
  'apostrophe-palette-global': {
    paletteFields: [ // array of fields, like a normal schema
      {
        name: 'backgroundColor',
        label: 'Background color of the website',
        type: 'color',
        selector: 'body',
        property: 'background-color',
      },
      {
        name: 'imageWidgetMargins',
        label: 'Vertical space between image widgets',
        type: 'range',
        selector: ['.c-image-widget', '.c-slideshow-widget'],
        property: ['margin-bottom', 'margin-top'],
        min: 0,
        max: 10,
        step: 0.1,
        unit: 'rem',
        mediaQuery: '(max-width: 59.99em)'
      },
      {
        name: 'buttonShadow',
        label: 'Button Shadow',
        type: 'color',
        selector: '.c-button',
        property: 'box-shadow',
        valueTemplate: '0 0 7px 2px %VALUE%'
      }
    ]
  }
}

paletteFields properties.

name

This becomes the name of the field when saved to the apostrophe-global document, be sure to avoid conflicts.

label

Normal schema label

type

A subset of of apostrophe-schema field types. Can take string, range, color, and select. Using other field types is permitted but not guaranteed.

selector

A string or array of strings to be used as CSS selectors. These are printed as-is, so it is valid to pass things like body, .template p, #someId [data-foo], etc. All selectors will be used to target the property property and give the value of the field.

property

A string or array of strings to be used as CSS properties. These are printed as-is and are used in conjunction with all selector properties and the value of the field itself.

unit (optional)

A string that is appended after the value of the field is printed as a CSS rule.

valueTemplate (optional)

Instead of the property value being derived solely from the field value, a template can be passed where the %VALUE% get replaced with the field value. Useful for complex CSS values that aren't totally being controlled by palette, like box-shadow.

mediaQuery (optional)

A string used to wrap a rule in a CSS media query. The format is as follows @media YOURMEDIAQUERY { YOURSELECTOR { YOURPROPERTY YOURUNIT; } }

  • Note, using the media query property will only apply that field's value to that media query. You may need multiple fields to fill out the spectrum of sizes

arrangePaletteFields

You get the opportunity to group your palette fields with a similar syntax you group normal apostrophe-schema fields. Fields can be nested at a max depth of 2 levels.

modules: {
  // ... project level configuration
  'apostrophe-palette-widgets': {},
  'apostrophe-palette': {},
  'apostrophe-palette-global': {
    paletteFields: [ ], // a bunch of palette fields
    arrangePaletteFields: [
      {
        name: 'colors',
        label: 'Color Settings',
        fields: ['backgroundColor', 'textColor', 'footerColor']
      },
      {
        name: 'type',
        label: 'Typography',
        fields: [
          {
            name: 'headline',
            label: 'Headline Style',
            fields: ['headlineSize', 'headlineFont', 'headlineColor']
          },
          {
            name: 'body',
            label: 'Body Copy Style',
            fields: ['bodySize', 'bodyFont', 'bodyLineHeight']
          }
        ]
      }
    ]
}

Including the interface and stylesheets in your template

The interface for interacting with the palette values is actually a special apostrophe-widget. There is a macro to help you put it on the page. You'll also need to add hooks for the stylesheet link (which brings in the styles as the exist when the page is loaded) and tag (which gets appended to when palette is changed, giving the editor immediate changes).

In layout.html

{% import 'apostrophe-palette-widgets:macros.html' as palette %}
<!-- ... other templating -->

  {% block extraHead %}
    {{ palette.stylesheetLink(data.global) }}
    {{ palette.stylesheetTag() }}
  {% endblock %}

  {% block beforeMain %}
    {% if data.user %} <!-- be sure to somehow safegaurd against non-editor situations, as performance could unnecessarily suffer -->
      {{ palette.palette(data.global, 'palette') }}
    {% endif %}
  {% endblock %}

Then you should be able to 'create' your palette widget by opening the drawer and clicking Add Palette. create a palette widget

Front-end events

Palette's widget has two front-end places you can hook into if you want to run some extra JavaScript before or after the submission of the new palette value. These would be handy places to send an editor a message, or use the submitted information to perform a more complex action on the page.

In lib/modules/apostrophe-palette-widgets/public/js/user.js

apos.define('apostrophe-palette-widgets', {
  construct: function (self, options) {

    // runs before the new palette values are sent to the server but does not block it
    self.beforeSubmit = function ($field, fieldValue, fieldSchema) {
      console.log($field); // the jQuery object for the schema field
      console.log(fieldValue); // the new value being sent to the server
      console.log(fieldSchema); // the changed field's schema
    };

    // runs after the front-end has recieved word that submission process has completed
    self.afterSubmit = function ($field, fieldValue, fieldSchema) {
      console.log($field); // the jQuery object for the schema field
      console.log(fieldValue); // the new value being sent to the server
      console.log(fieldSchema); // the changed field's schema
    };

  }
});

What actually happens?

Everytime the palette stylesheet is requested, Apostrophe generates a stylesheet based on the paletteFields and their values at the time of render and sends it to the browser. When an editor toggles the values of palette fields via it's widget, front-end JavaScript updates the <style> tag associated with palette with those changes. This makes sure the latest changes are last in the cascade. It also sends the new values to the server for sanitization and saving.

The generated stylesheets get properly cached until changes are made, at which time the browser is made aware there is a new version to fetch.